tag:blogger.com,1999:blog-8405107760807432973.post2128551827505427746..comments2024-01-04T09:55:32.459-08:00Comments on Java Concurrency (&c): Date-Race-Ful Lazy Initialization for PerformanceJeremy Mansonhttp://www.blogger.com/profile/04241094734813086257noreply@blogger.comBlogger53125tag:blogger.com,1999:blog-8405107760807432973.post-12956043491870294302019-08-18T12:08:02.990-07:002019-08-18T12:08:02.990-07:00LOL, looks like "broken" example should ...LOL, looks like "broken" example should be bolted https://bugs.openjdk.java.net/browse/JDK-8166842Vadzimhttps://www.blogger.com/profile/03059635660407148271noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-54656288689184056952019-06-24T19:56:54.147-07:002019-06-24T19:56:54.147-07:00@Edouard - Current hardware is not likely to produ...@Edouard - Current hardware is not likely to produce the surprising result. Compiler optimizations could conceivably produce this result if the code were changed such that hash field were accessed through two different aliases to the same memory location. <br /><br />I urge you not to program to what you think a particular hardware architecture may or may not do. First of all, compiler Jeremy Mansonhttps://www.blogger.com/profile/04241094734813086257noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-78998804459047724812019-06-10T23:41:03.949-07:002019-06-10T23:41:03.949-07:00@Jeremy, excellent article!!
And to be honest I&#...@Jeremy, excellent article!!<br /><br />And to be honest I'm still struggling to rationalize the broken code. In which situation the hardware would move the last read at the top, leave the second read as it is, and introduce this extra write to the local variable before the end of the if statement? It's so counter intuitive.<br /><br />This comment from hudson describes perfectly my KAISER Edouardhttps://www.blogger.com/profile/13132744100089269232noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-63240930828068073942017-10-30T23:11:43.272-07:002017-10-30T23:11:43.272-07:00@Shane: the example using a final wrapper in the a...@Shane: the example using a final wrapper in the article on wikipedia uses a lock to guarantee that the resource is only constructed once.<br />Jeremy Mansonhttps://www.blogger.com/profile/04241094734813086257noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-64227355352204493562017-10-11T23:21:31.593-07:002017-10-11T23:21:31.593-07:00Sorry for all the posts but I did some more think...Sorry for all the posts but I did some more thinking. The double checked locking example is OK under the assumption that we don't care whether we construct the resource more than once, analogous to assigning the hash code more than once in your example above. The final wrapper just ensures that the resource returned is fully constructed. Am I correct?Anonymoushttps://www.blogger.com/profile/08075895011915028580noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-14589635993097668672017-10-11T23:03:05.692-07:002017-10-11T23:03:05.692-07:00I just read your posts on immutability so what I u...I just read your posts on immutability so what I understand now is that one of the requirements for immutability objects is that the object mush be reachable from a final field so an object referenced from a non final field is not immutable whether the object itself is immutable or not - is that correct? That being the case, how does adding a final wrapper in the Wikipedia article on double Anonymoushttps://www.blogger.com/profile/08075895011915028580noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-11115870764639795892017-10-11T21:11:39.066-07:002017-10-11T21:11:39.066-07:00Thanks very much for your answer Jeremy. Can you e...Thanks very much for your answer Jeremy. Can you elaborate slightly please? In section 3.5.2 of the book Java Concurrency in Practice, the author states “Immutable objects can be used safely by any thread without additional synchronization, even when synchronization is not used to publish them”. What does he mean by this?Anonymoushttps://www.blogger.com/profile/08075895011915028580noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-57607973915025242072017-10-07T21:35:05.122-07:002017-10-07T21:35:05.122-07:00@Shane - it is incorrect to say that immutable obj...@Shane - it is incorrect to say that immutable objects are properly constructed even if published unsafely.<br /><br />Jeremy Mansonhttps://www.blogger.com/profile/04241094734813086257noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-18085866907162703062017-10-06T01:57:03.809-07:002017-10-06T01:57:03.809-07:00Hi, I have a question about visibility across thre...Hi, I have a question about visibility across threads. My understanding is that if you get a reference to an immutable object, even if it published unsafely (through an unprotected non volatile class field for example) then its guaranteed to be properly constructed (all the fields will have the values set in the constructor) but you aren’t guaranteed to see the latest version of the object due toAnonymoushttps://www.blogger.com/profile/08075895011915028580noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-82060428777851217392017-08-24T21:20:30.086-07:002017-08-24T21:20:30.086-07:00@thurston - there doesn't need to be something...@thurston - there doesn't need to be something explicitly addressing local variable elision. Chapter 17 is about how threads interact through memory. Changes to local variables are only visible within a thread. Single-threaded actions are not addressed.<br /><br />In general, the way local variable elimination is addressed is bullet 3 in 17.4.7. The compiler can do anything it wants Jeremy Mansonhttps://www.blogger.com/profile/04241094734813086257noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-59870912966477852242017-08-24T12:53:07.086-07:002017-08-24T12:53:07.086-07:00Does the JMM allow an optimizing compiler to remov...Does the JMM allow an optimizing compiler to remove a local variable altogether?<br /><br />so, <br />r1 = this.hash<br />r1 = computeHash()<br />this.hash = r1<br /><br />I'm not sure where in JLS $17.4 that there is an explicit proscription on eliding the local variable and updating this.hash directly; <br /><br />Certainly if you presumed a single-threaded execution that would be allowed, thurstonhttps://www.blogger.com/profile/09149288883351659243noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-54923908056335168722016-12-15T22:25:48.489-08:002016-12-15T22:25:48.489-08:00@Patrick - yes, the temp variable really is requir...@Patrick - yes, the temp variable really is required. Two unsynchronized reads can return different values. In practice, an implementation is unlikely to trigger a problem, but do you want to be the first one to find out?<br /><br />Also, yes, at a first glance, it looks to me as if the FinalWrapper would accomplish approximately the same thing as the volatile field. You are trading off an Jeremy Mansonhttps://www.blogger.com/profile/04241094734813086257noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-84371878370900827652016-12-03T15:38:58.755-08:002016-12-03T15:38:58.755-08:00Jeremy, I noticed in the Javamemorymodel-discussio...Jeremy, I noticed in the <a href="https://mailman.cs.umd.edu/mailman/private/javamemorymodel-discussion/2010-July/000423.html" rel="nofollow">Javamemorymodel-discussion mailing list</a> that Niklas Matthies used your String.hashCode example to justify an additional temp variable when Double-Checked Locking via a final field (this was back in Jul 22, 2010). That code has been sitting on <a href="Patrick Phttps://www.blogger.com/profile/10279236971202270566noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-67836365921676362016-03-05T10:31:11.706-08:002016-03-05T10:31:11.706-08:00@thurston: The memory model doesn't let you in...@thurston: The memory model doesn't let you introduce reads and writes of shared variables to introduce a previously non-existent race.Jeremy Mansonhttps://www.blogger.com/profile/04241094734813086257noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-27589942706862499192016-02-05T23:16:50.356-08:002016-02-05T23:16:50.356-08:00What I don't understand, is why the "beni...What I don't understand, is why the "benign data race" version (that has only one read of #hash in the source) is "benign" (viz. is guaranteed to never return zero).<br /><br />After all, it still doesn't meet the JMM guarantee of SC-DRF (there is still a data race).<br />There is nothing in the JMM, that treats "does a single read" methods as special (at Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-26432701158333997032015-11-07T17:23:54.878-08:002015-11-07T17:23:54.878-08:00@kostya: In my experience, having a data race in y...@kostya: In my experience, having a data race in your code often leads to serious bugs. Sometimes it is for memory model related reasons, but usually the code is wrong without any need to think about reordering or visibility issues.Jeremy Mansonhttps://www.blogger.com/profile/04241094734813086257noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-11280583583584069992015-11-05T06:13:31.128-08:002015-11-05T06:13:31.128-08:00Or do not read fields twice in method. Or do not u...Or do not read fields twice in method. Or do not use fields, use functional style programming and pass vars in fields. Or something else.<br /><br />Basically this is probably the second biggest disappointment in my life after I was told that there is no Santa.<br /><br />Using concurrent data structured will save you from these race conditions but probably will impact performance and memory Anonymoushttps://www.blogger.com/profile/16787517095071965588noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-80590703150261727542015-11-03T15:45:19.695-08:002015-11-03T15:45:19.695-08:00@kostya: The first snippet can't be reordered ...@kostya: The first snippet can't be reordered because it only reads hash once, not twice, so there is nothing to reorder.<br /><br />The general rule is, when writing code:<br /><br />75% of the time; First, try using an existing data structure to do what you want, preferably something in java.util.concurrent.<br />24% of the time: If that doesn't work, then use mutexes to protect your Jeremy Mansonhttps://www.blogger.com/profile/04241094734813086257noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-89687280949821054622015-11-03T13:01:31.917-08:002015-11-03T13:01:31.917-08:00I completely understand that :)
Good example abo...I completely understand that :) <br /><br />Good example about reordering is here: <br />https://assylias.wordpress.com/2013/02/01/java-memory-model-and-reordering/<br /><br />Which some kind of describes our situation.<br /><br />What worries me much that I should throw away a lot of code written so far :)<br /><br />So what should be the general rule when writing code? And why can't the Anonymoushttps://www.blogger.com/profile/16787517095071965588noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-53294121620540913732015-10-30T15:52:22.859-07:002015-10-30T15:52:22.859-07:00@Kostya - Another way to think about it is that, u...@Kostya - Another way to think about it is that, unless you have explicit synchronization, you can look at the statements in the thread, rearrange them to execute in a different order that works for just that thread in isolation, and execute them in the new order.<br /><br />For example, if you have this code:<br /><br />r1 = x;<br />r2 = x;<br />if (r1 == r2) <br /> y = 1;<br /><br />When you Jeremy Mansonhttps://www.blogger.com/profile/04241094734813086257noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-42672232676713839402015-10-30T12:47:24.930-07:002015-10-30T12:47:24.930-07:00Jeremy, a bit late comment as well :)
Can you pls...Jeremy, a bit late comment as well :)<br /><br />Can you pls elaborate on @Vladimir's question? <br />I do not see how can it work differently since we don't have any conditions inside 'if' statement. And once we git into it it should work exactly the same as for one thread. Sorry for repeating @Vladimir's question.Anonymoushttps://www.blogger.com/profile/16787517095071965588noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-75652983988041413862014-10-31T10:27:31.026-07:002014-10-31T10:27:31.026-07:00from thurston:
OK, I can see that the JMM permits...from thurston:<br /><br />OK, I can see that the JMM permits the reordering that makes the refactored hashCode() buggy, but I find it inconceivable that an actual CPU would exhibit such behavior.<br />Yes, there are 2 loads of #hash in the source, but the problematic out-of-order execution would only occur if:<br />a. javac, the JIT, and CPUs missed the opportunity to elide the second (program Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-52174856767606755242010-04-24T10:57:09.276-07:002010-04-24T10:57:09.276-07:00@Vladimir (sorry about the latency, I was on vacat...@Vladimir (sorry about the latency, I was on vacation)<br /><br />That sentence refers to the semantics of the evaluation of the thread, not the actual evaluation of the thread by the JVM.<br /><br />More specifically, looking at a single thread in isolation, the actions have to appear to the user as if they have been evaluated in that order. What the reads can return is dictated by the memory Jeremy Mansonhttps://www.blogger.com/profile/04241094734813086257noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-14022385974848360842010-04-09T00:33:28.581-07:002010-04-09T00:33:28.581-07:00Hi Jeremy,
I'm sorry for bothering you at such...Hi Jeremy,<br />I'm sorry for bothering you at such an old post? but could yoy clarify something?<br /> You wrote that valid transformation could be like this one:<br /><br />r1 = hash;<br />if (hash == 0) {<br /> r1 = hash = // calculate hash<br />}<br />return r1;<br /><br />The quote from JMM:<br />"Each time the evaluation of thread t generates an inter-thread action, it must match Anonymoushttps://www.blogger.com/profile/13564371949348295407noreply@blogger.comtag:blogger.com,1999:blog-8405107760807432973.post-5083503376831184442009-09-12T10:41:02.363-07:002009-09-12T10:41:02.363-07:00Ah, of course!
This is a valid transformation fo...Ah, of course! <br /><br />This is a valid transformation for a uniprocessor, but is a problem in a multi-processor setting. (hash could be changed by another thread between "r1 = hash" and "if hash == 0")<br /><br />Thanks, jeremy.ramnoreply@blogger.com