You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by "Maxim Ulanovskiy (JIRA)" <ji...@apache.org> on 2011/05/05 11:56:04 UTC

[jira] [Created] (TAP5-1520) ConcurrentModificationException while modify unclaimed private collection from different Threads

ConcurrentModificationException while modify unclaimed private collection from different Threads
------------------------------------------------------------------------------------------------

                 Key: TAP5-1520
                 URL: https://issues.apache.org/jira/browse/TAP5-1520
             Project: Tapestry 5
          Issue Type: Bug
          Components: tapestry-core
    Affects Versions: 5.2.5
            Reporter: Maxim Ulanovskiy


TestCase: create two parallel requests to the page bellow
first request to read action - /TestConcurrency.read
second request to write action - /TestConcurrency.write

TestConcurrency.tml:
...
<t:actionlink t:id="read">read</t:actionlink>
<t:actionlink t:id="write">write</t:actionlink>
...

public class TestConcurrency {

    private List<String> testDie = new ArrayList<String>();
    
    public void onActivate() {
        for(int i=0; i<1000; i++)
            testDie.add("init");
    }

    void onActionFromRead() {
        for(String s : testDie)
            System.out.println(s);
    }
    void onActionFromWrite() {
        for(int i=0; i<100000; i++)
            testDie.add("testDie"+i);
    }
}

>From what I've found out with debugger is that direct access to List<String> testDie is replaced with UnclaimedFieldWorker.UnclaimedFieldConduit  but when PerthreadManagerImpl is called  it fails to find thread local value in internal map and returnes default value - the same object for both threads:
public class PerthreadManagerImpl {

<T> PerThreadValue<T> createValue(final Object key)
    {
        return new PerThreadValue<T>()
        {
            public T get()
            {
                return get(null);
            }

            public T get(T defaultValue)
            {
                Map map = getPerthreadMap();
//              NO SUCH KEY IN map 
                if (map.containsKey(key))
                {
                    Object storedValue = map.get(key);

                    if (storedValue == NULL_VALUE)
                        return null;

                    return (T) storedValue;
                }

                return defaultValue;
            }

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

Re: [jira] [Closed] (TAP5-1520) ConcurrentModificationException while modify unclaimed private collection from different Threads

Posted by "Thiago H. de Paula Figueiredo" <th...@gmail.com>.
On Thu, 05 May 2011 13:19:20 -0300, Howard Lewis Ship <hl...@gmail.com>  
wrote:

> I'm beginning to think that we should simply check that the
> initialization of any field is an immutable value; we know what main
> JDK classes are immutable (String, Boolean, Number) and can have a
> service (combined with an @Immutable annotation) go further.

And throw and exception when the field is not immutable? +1!

> This is a recurring question on the list, but not one that fits into
> an FAQ meaningfully ... I think the framework needs to change.

Yep . . .

-- 
Thiago H. de Paula Figueiredo
Independent Java, Apache Tapestry 5 and Hibernate consultant, developer,  
and instructor
Owner, Ars Machina Tecnologia da Informação Ltda.
http://www.arsmachina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org


Re: [jira] [Closed] (TAP5-1520) ConcurrentModificationException while modify unclaimed private collection from different Threads

Posted by Howard Lewis Ship <hl...@gmail.com>.
I'm beginning to think that we should simply check that the
initialization of any field is an immutable value; we know what main
JDK classes are immutable (String, Boolean, Number) and can have a
service (combined with an @Immutable annotation) go further.

This is a recurring question on the list, but not one that fits into
an FAQ meaningfully ... I think the framework needs to change.

On Thu, May 5, 2011 at 5:35 AM, Thiago H. de Paula Figueiredo (JIRA)
<ji...@apache.org> wrote:
>
>     [ https://issues.apache.org/jira/browse/TAP5-1520?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
>
> Thiago H. de Paula Figueiredo closed TAP5-1520.
> -----------------------------------------------
>
>    Resolution: Invalid
>
> Hi!
>
> The error here is in your code: you should never initialize a field with a non-atomic value. An event handler like onActivate(), @BeginRender or some event triggered by Form.
>
> Please post in the user mailing list before posting bugs.
>
> Cheers!
>
> Thiago
>
>> ConcurrentModificationException while modify unclaimed private collection from different Threads
>> ------------------------------------------------------------------------------------------------
>>
>>                 Key: TAP5-1520
>>                 URL: https://issues.apache.org/jira/browse/TAP5-1520
>>             Project: Tapestry 5
>>          Issue Type: Bug
>>          Components: tapestry-core
>>    Affects Versions: 5.2.5
>>            Reporter: Maxim Ulanovskiy
>>
>> TestCase: create two parallel requests to the page bellow
>> first request to read action - /TestConcurrency.read
>> second request to write action - /TestConcurrency.write
>> TestConcurrency.tml:
>> ...
>> <t:actionlink t:id="read">read</t:actionlink>
>> <t:actionlink t:id="write">write</t:actionlink>
>> ...
>> public class TestConcurrency {
>>     private List<String> testDie = new ArrayList<String>();
>>
>>     public void onActivate() {
>>         for(int i=0; i<1000; i++)
>>             testDie.add("init");
>>     }
>>     void onActionFromRead() {
>>         for(String s : testDie)
>>             System.out.println(s);
>>     }
>>     void onActionFromWrite() {
>>         for(int i=0; i<100000; i++)
>>             testDie.add("testDie"+i);
>>     }
>> }
>> From what I've found out with debugger is that direct access to List<String> testDie is replaced with UnclaimedFieldWorker.UnclaimedFieldConduit  but when PerthreadManagerImpl is called  it fails to find thread local value in internal map and returnes default value - the same object for both threads:
>> public class PerthreadManagerImpl {
>> <T> PerThreadValue<T> createValue(final Object key)
>>     {
>>         return new PerThreadValue<T>()
>>         {
>>             public T get()
>>             {
>>                 return get(null);
>>             }
>>             public T get(T defaultValue)
>>             {
>>                 Map map = getPerthreadMap();
>> //              NO SUCH KEY IN map
>>                 if (map.containsKey(key))
>>                 {
>>                     Object storedValue = map.get(key);
>>                     if (storedValue == NULL_VALUE)
>>                         return null;
>>                     return (T) storedValue;
>>                 }
>>                 return defaultValue;
>>             }
>
> --
> This message is automatically generated by JIRA.
> For more information on JIRA, see: http://www.atlassian.com/software/jira
>



-- 
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to
learn how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org


[jira] [Closed] (TAP5-1520) ConcurrentModificationException while modify unclaimed private collection from different Threads

Posted by "Thiago H. de Paula Figueiredo (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/TAP5-1520?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Thiago H. de Paula Figueiredo closed TAP5-1520.
-----------------------------------------------

    Resolution: Invalid

Hi!

The error here is in your code: you should never initialize a field with a non-atomic value. An event handler like onActivate(), @BeginRender or some event triggered by Form.

Please post in the user mailing list before posting bugs.

Cheers!

Thiago

> ConcurrentModificationException while modify unclaimed private collection from different Threads
> ------------------------------------------------------------------------------------------------
>
>                 Key: TAP5-1520
>                 URL: https://issues.apache.org/jira/browse/TAP5-1520
>             Project: Tapestry 5
>          Issue Type: Bug
>          Components: tapestry-core
>    Affects Versions: 5.2.5
>            Reporter: Maxim Ulanovskiy
>
> TestCase: create two parallel requests to the page bellow
> first request to read action - /TestConcurrency.read
> second request to write action - /TestConcurrency.write
> TestConcurrency.tml:
> ...
> <t:actionlink t:id="read">read</t:actionlink>
> <t:actionlink t:id="write">write</t:actionlink>
> ...
> public class TestConcurrency {
>     private List<String> testDie = new ArrayList<String>();
>     
>     public void onActivate() {
>         for(int i=0; i<1000; i++)
>             testDie.add("init");
>     }
>     void onActionFromRead() {
>         for(String s : testDie)
>             System.out.println(s);
>     }
>     void onActionFromWrite() {
>         for(int i=0; i<100000; i++)
>             testDie.add("testDie"+i);
>     }
> }
> From what I've found out with debugger is that direct access to List<String> testDie is replaced with UnclaimedFieldWorker.UnclaimedFieldConduit  but when PerthreadManagerImpl is called  it fails to find thread local value in internal map and returnes default value - the same object for both threads:
> public class PerthreadManagerImpl {
> <T> PerThreadValue<T> createValue(final Object key)
>     {
>         return new PerThreadValue<T>()
>         {
>             public T get()
>             {
>                 return get(null);
>             }
>             public T get(T defaultValue)
>             {
>                 Map map = getPerthreadMap();
> //              NO SUCH KEY IN map 
>                 if (map.containsKey(key))
>                 {
>                     Object storedValue = map.get(key);
>                     if (storedValue == NULL_VALUE)
>                         return null;
>                     return (T) storedValue;
>                 }
>                 return defaultValue;
>             }

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Closed] (TAP5-1520) ConcurrentModificationException while modify unclaimed private collection from different Threads

Posted by "Thiago H. de Paula Figueiredo (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/TAP5-1520?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Thiago H. de Paula Figueiredo closed TAP5-1520.
-----------------------------------------------

    Resolution: Invalid

Hi!

The error here is in your code: you should never initialize a field with a non-atomic value. An event handler like onActivate(), @BeginRender or some event triggered by Form.

Please post in the user mailing list before posting bugs.

Cheers!

Thiago

> ConcurrentModificationException while modify unclaimed private collection from different Threads
> ------------------------------------------------------------------------------------------------
>
>                 Key: TAP5-1520
>                 URL: https://issues.apache.org/jira/browse/TAP5-1520
>             Project: Tapestry 5
>          Issue Type: Bug
>          Components: tapestry-core
>    Affects Versions: 5.2.5
>            Reporter: Maxim Ulanovskiy
>
> TestCase: create two parallel requests to the page bellow
> first request to read action - /TestConcurrency.read
> second request to write action - /TestConcurrency.write
> TestConcurrency.tml:
> ...
> <t:actionlink t:id="read">read</t:actionlink>
> <t:actionlink t:id="write">write</t:actionlink>
> ...
> public class TestConcurrency {
>     private List<String> testDie = new ArrayList<String>();
>     
>     public void onActivate() {
>         for(int i=0; i<1000; i++)
>             testDie.add("init");
>     }
>     void onActionFromRead() {
>         for(String s : testDie)
>             System.out.println(s);
>     }
>     void onActionFromWrite() {
>         for(int i=0; i<100000; i++)
>             testDie.add("testDie"+i);
>     }
> }
> From what I've found out with debugger is that direct access to List<String> testDie is replaced with UnclaimedFieldWorker.UnclaimedFieldConduit  but when PerthreadManagerImpl is called  it fails to find thread local value in internal map and returnes default value - the same object for both threads:
> public class PerthreadManagerImpl {
> <T> PerThreadValue<T> createValue(final Object key)
>     {
>         return new PerThreadValue<T>()
>         {
>             public T get()
>             {
>                 return get(null);
>             }
>             public T get(T defaultValue)
>             {
>                 Map map = getPerthreadMap();
> //              NO SUCH KEY IN map 
>                 if (map.containsKey(key))
>                 {
>                     Object storedValue = map.get(key);
>                     if (storedValue == NULL_VALUE)
>                         return null;
>                     return (T) storedValue;
>                 }
>                 return defaultValue;
>             }

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira