I have a question regarding synchronization of code that is executed by several threads:
As far as I know each thread has its own stack, hence, non-static variables exist in different locations in the memory for each thread (for X threads there are X stacks that include all non-static variables). So why there's a need to synchronize anything?
I mean, if the code that the threads execute includes some class variable v1, then each thread has its own "instance" of v1 (different memory address), and no other thread can "touch" it... isn't it so?
Local variables, primitives and references are implicitly thread-local. However, objects referenced can be shared and when a thread can modify a shared object it is highly likely you will need
synchronised
, a Lock or some other strategy to ensure thread safety."non-static variables exist in different locations" could not possibly be correct. In Java, you never directly get to know anything of "the stack". All of your class variables, static or instance, come from the heap. As a java developer, however, you don't really care about that.
The only time you don't care about thread-safety is when your classes are immutable (don't change after construction) OR you aren't ever doing anything in threads. If your classes don't fall into these two categories, you need to think about making them thread-safe.
The more immutability you can get into your designs, the easier the Threading issues are to reason about and overcome.
Nrj has got the right idea.
Stack yes (think of a call stack, local variables), but class variables live in the heap and you have to synchronize access to them:)
This is not true, so the answer to
is no. Threads can touch object instances allocated and modified by other threads and the burden is on the programmer to ensure this does not affect program correctness.
Class member variables exist in a single place in memory per-class instance, not per thread. It is true that between memory barriers (think the start
{
and end}
ofsynchronized
), that a thread may have a cache of the state of an object, but that is not the same as the language mandating per-thread storage. The "memory for each thread" is its stack which does not contain object members* -- only references to objects.The best way to think of it is that there is one location on the heap for each object, but that there might be multiple reads&|writes involving that memory location happening at the same time.
I can see how you would come to the conclusions you did if you heard that threads allocate objects in different parts of the heap. Some JVMs have an optimization whereby they do thread-local allocation but that does not prevent other threads from accessing those objects.
* - it's possible that JVM optimizations allow some objects to be allocated on the stack.
On a same object instance, if your method is not synchronized, there is no guarantee that the same code is not executed twice in different threads --> havoc! Which is the correct value?
At the minimum, you want to declare methods accessing a variable as synchronized. If you want more fine-grained control, you can use, for instance, a
ReentrantReadWriteLock
.Declaring a method synchronized synchronizes on the object instance, so this is safe.
Only primitive types, such as
int
are guaranteed to be allocated on the stack. Objects and arrays are all typically stored in the heap unless Escape Analysis determines the scope of the object is 'restricted to the scope of the procedure'.