Oops: "use x and y somehow" should read "use y and z somehow" in the example I gave. Hopefully that's not too confusing.
On Tue, Sep 25, 2018 at 11:09 PM Tom Lee <[email protected]> wrote: > How to interpret a citation given by Cezary?: "If x and y are actions of >> the same thread and x comes before y in program order, then hb(x, y)." > > > This is a great question! Hopefully I'm not too far off-base but I think > it comes down to effects/"visibility" and this statement hints at the kinds > of optimization that might be legal. Assume a single thread of execution > where reordering is in play. *Instructions* implementing the actions can > be reordered in such a way that we perform all the work required to execute > *actions* x and y, but until the effects of those operations "leak" > you're still not strictly violating the hb(x, y) rule. > > For example, sticking to the "single thread of execution" example and > local variables: > > a: x =1 > b: y = 2 > c: z = x + y * 3 > d: y = z > e...: (use x and y somehow) > > We could reorder the underlying instructions such that we compute z > directly & simply omit the assignment to x and y such that what actually > gets executed by the CPU looks more like: > > a: (optimized away) > b: (optimized away) > c: z = 3 * 2 + 1 > d: y = z > e: (use x and y somehow) > > Does it matter that we've eliminated the assignments and reordered some of > the arithmetic? Probably not: we've changed the underlying instructions but > as far as the *effects *are concerned we ultimately "see" hb(a,b) -> > hb(b,c) -> hb(c,d) -> hb(d,e...) and a correct execution of our program! Of > course, this is easier to reason about when the instructions/actions > involved are simple. Replace simple arithmetic with method calls, volatile > reads & writes, allocation, threads, etc. and it obviously gets a whole lot > messier. > > (No doubt somebody out there can formalize what I'm trying to get across > here, I'm sort of running on intuition. :)) > > On Tue, Sep 25, 2018 at 10:34 PM John Hening <[email protected]> wrote: > >> Tom, >> >> Actually you right. I get it! >> >> Gil, >> thanks for your note. You obviously right. If I use multithreaded >> executor I got a lot races in a result. >> So, does it mean that my both version of example are correct? >> >> How to interpret a citation given by Cezary?: "If x and y are actions of >> the same thread and x comes before y in program order, then hb(x, y)." >> For my eye the key is in interpreting of program order. So, if we have >> two statements [X, Y] and order of execution does not matter because both >> are intrathread-consistent it means that [Y,X] are in program order and >> HB(Y,X) by a rule I cite above. >> >> So, If we had no Executor's (and no other) guarantee it could be >> reordered. >> >> >> W dniu środa, 26 września 2018 04:49:21 UTC+2 użytkownik Gil Tene napisał: >>> >>> As Tom noted, The Executor's submission happens-before promise prevents >>> a reordering of (1) and (2) above. >>> >>> Note that, as written, the reason you you don't have data races between >>> (2) and (2) is that executor is known to be a single threaded executor (and >>> will only run one task at a time). Without that quality, you would have >>> plenty of (2) vs. (2) races. It is not that "doers contain different >>> objects": your code submits executions of functions using the same x member >>> of xs to all doers, and it is only the guaranteed serialization in your >>> chosen executor implementation that prevents x,f()s from racing on the same >>> x... >>> >>> On Tuesday, September 25, 2018 at 8:52:14 AM UTC-7, John Hening wrote: >>>> >>>> public class Test { >>>> ArrayList<X> xs; >>>> ArrayList<Doer> doers; >>>> Executor executor = Executors.newSingleThreadExecutor(); >>>> >>>> static class Doer { >>>> public void does(X x){ >>>> x.f(); >>>> // (2) >>>> } >>>> } >>>> >>>> void test() { >>>> for(X x : xs){ >>>> x.f(); >>>> // (1) >>>> >>>> for(Doer d : doers) { >>>> executor.execute(() -> d.does(x)); >>>> } >>>> } >>>> } >>>> } >>>> >>>> >>>> >>>> >>>> For my eye, if X.f is not synchronized it is incorrect because of two >>>> facts (and only that two facts): >>>> >>>> 1. Obviously, there is data race between (1) and (2). There are no more >>>> data races here. (doers contains different objects) >>>> 2. There is no guarantee that (1) will be executed before (2). Yes? >>>> >>>> If X.f would be synchronized that code will be correct because: >>>> 1. There is no data race. >>>> 2. There is guarantee that (1) will be executed before (2) because (1) >>>> is a synchronization action and Executor.execute is also a synchronization >>>> access (not specifically execute itself) >>>> >>>> Yes? >>>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "mechanical-sympathy" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected]. >> For more options, visit https://groups.google.com/d/optout. >> > > > -- > *Tom Lee */ http://tomlee.co / @tglee <http://twitter.com/tglee> > > -- *Tom Lee */ http://tomlee.co / @tglee <http://twitter.com/tglee> -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
