You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by "Thiago H. de Paula Figueiredo (JIRA)" <ji...@apache.org> on 2011/05/05 14:35:03 UTC
[jira] [Closed] (TAP5-1520) ConcurrentModificationException while
modify unclaimed private collection from different Threads
[ 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
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