Reputation:
From java in a nutshell
In Java, all Java application threads in a process have their own stacks (and local variables) but share a single heap. This makes it very easy to share objects between threads, as all that is required is to pass a reference from one thread to another.
This leads to a general design principle of Java—that objects are visible by default. If I have a reference to an object, I can copy it and hand it off to another thread with no restrictions. A Java reference is essentially a typed pointer to a location in memory—and threads share the same address space, so visible by default is a natural model.
From Java Concurrency in Practice
Visibility is subtle because the things that can go wrong are so counterintuitive. In a single-threaded environment, if you write a value to a variable and later read that variable with no intervening writes, you can expect to get the same value back. This seems only natural. It may be hard to accept at first, but when the reads and writes occur in different threads, this is simply not the case. In general, there is no guarantee that the reading thread will see a value written by another thread on a timely basis, or even at all. In order to ensure visibility of memory writes across threads, you must use synchronization.
When a thread reads a variable without synchronization, it may see a stale value.
So why does Java in a Nutshell says objects are visible to all threads, while Java Concurrency in Practice says no guarantee that a reading thread sees a value written by another thread on a timely basis? They don't seem consistent.
Thanks.
Upvotes: 4
Views: 1078
Reputation: 10084
In Java, all Java application threads in a process have their own stacks (and local variables) but share a single heap. This makes it very easy to share objects between threads, as all that is required is to pass a reference from one thread to another.
This leads to a general design principle of Java—that objects are visible by default.
I suppose that these statements are strictly true ... but they are misleading because they don't convey the whole truth. For example, what does the author mean when he says "...that objects are visible by default."
Any thread executing on a Java JVM does not have de facto visibility to all the objects on the JVM's heap. If we define visibility as "the ability to access by reference", then a thread only has visibility to objects:
In fact, an important and commonly used thread safety policy in Java concurrent programming is thread confinement. If a thread holds a reference to an object to which only it has access and which is not published to any other thread, then that object is thread safe. That object can be safely mutated by the thread in which it is confined without any further regard to visibility and atomicity ... as long as it is correctly thread confined.
In other words, an object that is thread confined, no matter where it is on the JVM heap, is not visible to any other thread that may be running on that same JVM by virtue of being inaccessible.
since shared objects are stored in the heap shared by threads, why some threads might not see the most updated value by other threads?
In this age of multi-core processors, each CPU on which a JVM may be running has its own levels of local cache memory that no other core can see. This gets to the heart of why values written to variables in one thread are not guaranteed to be visible to another thread: the Java Memory Model makes no guarantees when values written by one thread will become visible to other threads because it does not specify when cached values will be written back from cache to memory.
It is, in fact, usual for the unsynchronized access of values to be stale (or inconsistent) when those values are accessed by many threads. Depending on the state transition that is occurring, thread safety in a concurrent environment in which many threads may be accessing the same value, may require:
in order to achieve a thread safety policy that allows your program to be correct.
Upvotes: 1
Reputation: 3563
"So why does Java in a Nutshell says objects are visible to all threads" --> As your quote says, in Java objects are allocated on the heap. A 'global' heap available for the entire JVM. Whereas in other languages (e.g. C++) objects can also be allocated on a stack. Objects on a heap can be passed to other threads, using different stacks. Objects on a stack can only be used on the thread using the same stack, as the stack's content will change beyond control of another thread.
"while Java Concurrency in Practice says no guarantee that a reading thread sees a value written by another thread on a timely basis?" -> This is another issue, as this is about values of memory locations. Though they are reachable compilers and CPUs try to optimize reading from or writing to this memory locations and will heavily cache the value by assuming "I'm the only one reading and writing to this memory location". So if one thread modifies a memory location's value the other thread does not know it has changed and will not read it new. This makes the program much faster. By declaring a variable volatile
you are telling the compiler that another thread may change the value at will and the compiler will use this to create code that doesn't cache the value.
Finally, multithreading is much more difficult than adding volatile
, or using synchronized
, one really needs to dive into the topic of the issues you will encounter when using multiple threads.
Upvotes: 1