Atomicity of Reads and Writes for Variables in Java

时间秒杀一切 提交于 2019-12-06 03:09:39

To the best of my knowledge there is no atomic i1 = i2 operation. You can atomically read an int and you can atomically write to one, but you can't do both in the same operation with synchronization. So i1 = i2 is two different atomic operations, a read followed by a write. You are guaranteed that nothing will interleave the read operation so you won't see partial updates to i2 when you read it, and you are guaranteed that nothing will interleave the write to i1, but there's no guarantee that nothing will happen in between those two atomic operations.

Lets say Thread t1 is going to do:

i2 = 10
i1 = i2

And thread t2 is going to do:

i1 = 7
i2 = 18
System.out.println(i1)

What you are guaranteed is that t1 will end up assigning either 10 or 18 to i1 but you can't know which. However, you are guaranteed it can't be any other value because the read of i2 and the write to i1 are atomic so you can't end up seeing some of the bits of i2 while it's being modified. Similarly, t2 is guaranteed to print either 10, 18, or 7 and it can't print anything else. However, without synchronization there's no way to know which of those 3 values it will end up printing.

Gray

... it means that during this atomic operation (executed by threadX), no other threadY is allowed to access (for either read or write) that same variable i2, hence, no other threadY, is allowed to access that same variable during the atomic operation, so some form of blocking does exist.

No you didn't get it right.

Atomic operations mean that threads can not see values in a partial state. The assignment is atomic depending on the underlying architecture running your JVM and the data size of i1 and i2. I believe that Java says that int fields are atomically assigned but long (and double) may not be because it may take multiple operations by the CPU.

Atomic actions cannot be interleaved, so they can be used without fear of thread interference.

This is right. If i1 is 1 and i2 is 2 and threadX executes the assignment, then any other thread will either see the value of i1 as 1 (the old value) or 2 (the new value). ThreadY won't see it be some sort of half-way between 1 or 2 because that assignment is atomic even if multiple threads are updating the value of i1.

But what is really confusing the matter is that there are two concepts going on here: atomicity and memory synchronization. With threads, each CPU has its own memory cache so that memory operations are first made to the local memory and then these changes are written to main memory. A thread might see an old copy of i1 in its local cached memory even though another thread has updated main memory already. Even worse is when two threads have updated the value of i1 in their local memory and depending on their order of operations (which is highly random) one thread's value will overwrite the other thread's write to main memory. It's extremely hard to know which one will win the race condition.

As a note - atomicity does not mean "all other threads will be blocked until the value is ready.

Right. This is trying to let you know that there is no locking involved at all here. There are no guarantees as to the value that ThreadY will see. ThreadY could also be updating i1 at the same exact time to the value 3 and then other threads could see it as 1, 2, or 3 depending on the order of operations and whether or not those threads cross memory barriers when the cache flushing and updating is enforced.

The way we control fields and objects that are shared between threads is with the synchronized keyword, which gives a thread unique access to a resource. There are also Locks and other mechanisms to provide mutex. We also can force memory barriers by adding a volatile keyword to a field which means that any read or write to the field will be made to main memory. Both synchronized and volatile ensure proper publishing of data and ordering of operations.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!