I am trying to understand the two methods here in java unsafe:
public native short getShortVolatile(Object var1, long var2);
vs
public native short getShort(Object var1, long var2);
What is the real difference here? What does volatile here really work for? I found API doc here: http://www.docjar.com/docs/api/sun/misc/Unsafe.html#getShortVolatile(Object,%20long)
But it does not really explain anything for the difference between the two functions.
My understanding is that, for volatile, it only matters when we do write. To me, it should make sense that we call putShortVolatile and then for reading, we can simply call getShort() since volatile write already guarantee the new value has been flushed into main memory.
Please kindly correct me if anything is wrong. Thanks!
Here there is an article: http://mydailyjava.blogspot.it/2013/12/sunmiscunsafe.html
Unsafe supports all primitive values and can even write values without hitting thread-local caches by using the volatile forms of the methods
getXXX(Object target, long offset): Will read a value of type XXX from target's address at the specified offset.
getXXXVolatile(Object target, long offset): Will read a value of type XXX from target's address at the specified offset and not hit any thread local caches.
putXXX(Object target, long offset, XXX value): Will place value at target's address at the specified offset.
putXXXVolatile(Object target, long offset, XXX value): Will place value at target's address at the specified offset and not hit any thread local caches.
UPDATE:
You can find more information about memory management and volatile fields on this article: http://cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html (it contains also some example of reordering).
In multiprocessor systems, processors generally have one or more layers of memory cache, which improves performance both by speeding access to data (because the data is closer to the processor) and reducing traffic on the shared memory bus (because many memory operations can be satisfied by local caches.) Memory caches can improve performance tremendously, but they present a host of new challenges. What, for example, happens when two processors examine the same memory location at the same time? Under what conditions will they see the same value?
Some processors exhibit a strong memory model, where all processors see exactly the same value for any given memory location at all times. Other processors exhibit a weaker memory model, where special instructions, called memory barriers, are required to flush or invalidate the local processor cache in order to see writes made by other processors or make writes by this processor visible to others.
The issue of when a write becomes visible to another thread is compounded by the compiler's reordering of code. If a compiler defers an operation, another thread will not see it until it is performed; this mirrors the effect of caching. Moreover, writes to memory can be moved earlier in a program; in this case, other threads might see a write before it actually "occurs" in the program.
Java includes several language constructs, including volatile, final, and synchronized, which are intended to help the programmer describe a program's concurrency requirements to the compiler. The Java Memory Model defines the behavior of volatile and synchronized, and, more importantly, ensures that a correctly synchronized Java program runs correctly on all processor architectures.
As you can see in the section What does volatile do?
Volatile fields are special fields which are used for communicating state between threads. Each read of a volatile will see the last write to that volatile by any thread; in effect, they are designated by the programmer as fields for which it is never acceptable to see a "stale" value as a result of caching or reordering. The compiler and runtime are prohibited from allocating them in registers. They must also ensure that after they are written, they are flushed out of the cache to main memory, so they can immediately become visible to other threads. Similarly, before a volatile field is read, the cache must be invalidated so that the value in main memory, not the local processor cache, is the one seen.
There are also additional restrictions on reordering accesses to volatile variables. Accesses to volatile variables could not be reordered with each other. Is now no longer so easy to reorder normal field accesses around them. Writing to a volatile field has the same memory effect as a monitor release, and reading from a volatile field has the same memory effect as a monitor acquire. In effect, because the new memory model places stricter constraints on reordering of volatile field accesses with other field accesses, volatile or not, anything that was visible to thread A when it writes to volatile field f becomes visible to thread B when it reads f.
So the difference is that the setXXX() and getXXX() could be reorded or could use cached values not yet synchronized between the threads, while the setXXXVolatile() and the getXXXVolatile() won't be reordered and will use always the last value.
The thread local cache is a temporary storage used from java to improve performances: the data will be written/read into/from the cache before to be flushed on the memory.
In a single thread context you can use both the not-volatile than the volatile version of those methods, there will be no difference. When you write something, it doesn't matter if it is written immediately on memory or just in the thread local cache: when you'll try to read it, you'll be in the same thread, so you'll get the last value for sure (the thread local cache contain the last value).
In a multi thread context, instead, the cache could give you some throubles.
If you init an unsafe object, and you share it between two or more threads, each of those threads will have a copy of it into its local cache (the two threads could be runned on different processors, each one with its cache).
If you use the setXXX() method on a thread, the new value could be written in the thread local cache, but not yet in the memory. So it could happens that just one of the multiple thread contains the new value, while the memory and the other threadds local cache contain the old value. This could bring to unexpected results. The setXXXVolatile() method will write the new value directly on memory, so also the other threadds will be able to access to the new value (if they use the getXXXVolatile() methods).
If you use the getXXX() method, you'll get the local cache value. So if another thread has changed the value on the memory, the current thread local cache could still contains the old value, and you'll get unexpeted results. If you use the getXXXVolatile() method, you'll access directly to the memory, and you'll get the last value for sure.
Using the example of the previous link:
class DirectIntArray {
private final static long INT_SIZE_IN_BYTES = 4;
private final long startIndex;
public DirectIntArray(long size) {
startIndex = unsafe.allocateMemory(size * INT_SIZE_IN_BYTES);
unsafe.setMemory(startIndex, size * INT_SIZE_IN_BYTES, (byte) 0);
}
}
public void setValue(long index, int value) {
unsafe.putInt(index(index), value);
}
public int getValue(long index) {
return unsafe.getInt(index(index));
}
private long index(long offset) {
return startIndex + offset * INT_SIZE_IN_BYTES;
}
public void destroy() {
unsafe.freeMemory(startIndex);
}
}
This class use the putInt and the getInt to write the values into an array allocated on the memory (so outside the heap space).
As said before, those methods write the data in the thread local cache, not immediately in the memory. So when you use the setValue() method, the local cache will be updated immediately, the allocated memory will be updated after a while (it depends from the JVM implementation).
In a single thread context that class will work without problem.
In a multi threads context it could fails.
DirectIntArray directIntArray = new DirectIntArray(maximum);
Runnable t1 = new MyThread(directIntArray);
Runnable t2 = new MyThread(directIntArray);
new Thread(t1).start();
new Thread(t2).start();
Where MyThread is:
public class MyThread implements Runnable {
DirectIntArray directIntArray;
public MyThread(DirectIntArray parameter) {
directIntArray = parameter;
}
public void run() {
call();
}
public void call() {
synchronized (this) {
assertEquals(0, directIntArray.getValue(0L)); //the other threads could have changed that value, this assert will fails if the local thread cache is already updated, will pass otherwise
directIntArray.setValue(0L, 10);
assertEquals(10, directIntArray.getValue(0L));
}
}
}
With putIntVolatile() and getIntVolatile(), one of the two threads will fails for sure (the second threads will get 10 instead of 0).
With putInt() and getInt(), both the threads could finish with success (because the local cache of both threads could still contains 0 if the writer cache wasn't been flushed or the reader cache wasn't been refreshed).
I think that getShortVolatile is reading a plain short from an Object, but treats it as a volatile; it's like reading a plain variable and inserting the needed barriers (if any) yourself.
Much simplified (and to some degree wrong, but just to get the idea). Release/Acquire semantics:
Unsafe.weakCompareAndSetIntAcquire // Acquire
update some int here
Unsafe.weakCompareAndSetIntRelease // Release
As to why this is needed (this is for getIntVolatile, but the case still stands), is to probably enforce non-reorderings. Again, this is a bit beyond me and Gil Tene explaining this is FAR more suited.
Related
Assuming the following class:
public class Counter {
private long val;
private final ReadWriteLock reentrantLock = new ReentrantReadWriteLock();
public Counter(long val) {
this.val = val;
}
public void increment() {
try {
reentrantLock.writeLock().lock();
val++;
} finally {
reentrantLock.writeLock().unlock();
}
}
public long getVal() {
try {
reentrantLock.readLock().lock();
return this.val;
} finally {
reentrantLock.readLock().unlock();
}
}
}
Ignoring that we could use AtomicLong, what bad things could happen when we read without a lock and why are these things happening.
My assumptions:
Not the latest value (a new writer thread could update the value +1 in the moment we read), so we would be at least one value behind
Some garbage in-between writes value (can that happen in java)
Another assumption:
There's no risk of not seeing any writer value, since the WriteLock enforces memory barriers which will flush the value to main memory
Anything I'm missing?
The bad thing that can (in theory) happen is if readers don't use the read locks is that they could see a stale value of the counter; i.e. a value that is NOT the latest value written by a writer.
In Java, primitive locks and Lock classes have two functions:
The provide mutual exclusion.
They provide threads with certain guarantees about visibility of values in shared variables.
Without the visibility guarantees provided by correct use of locks (and some other things), changes made by one thread may not be visible to another thread.
Unfortunately, while there is no guarantee that that one thread won't see the correct value, there is no guarantee that it will see an incorrect one either. The actual behavior depends on a number of different factors that are difficult to analyze ... and are implementation and platform dependent. So demonstrating that a thread can see stale values can be difficult. Likewise, you cannot prove that a program doesn't have that kind of flaw by testing it. And if a program does have this kind of flaw, it is likely to be hard to reproduce ... especially when you are using a debugger.
Not the latest value (a new writer thread could update the value +1 in the moment we read), so we would be at least one value behind.
In fact, the reader could see a value that many updates behind ... or even the initial value of val.
Some garbage in-between writes value (can that happen in java)
This is also possible. The JMM treats a long or a double as two separate memory cells, so an reader that doesn't use locks could see a high word from one value and a low word from a different value.
There's no risk of not seeing any writer value, since the WriteLock enforces memory barriers which will flush the value to main memory.
This is incorrect from two respects:
That is an implementation detail. The JMM says nothing about memory barriers, and neither do the relevant javadocs.
In fact if the reader is not using a read lock, the JIT compiler might emit code that caches the value of val in a register ... and not bother to re-read it from main memory in all circumstances.
Note that this is also an implementation detail. But this is a behavior that is permitted by the JMM. When the reader doesn't use the lock, there will be no happens before relation between the write and the subsequent read. With out that relation, the code doesn't need to meet the visibility guarantee.
in Java Performance Tuning by Jack Shirazi it writes:
This means that access and update of variables are automatically synchronized (as long as they are not longs or doubles). If a method consists solely of a variable access or assignment, there is no need to make it synchronized for thread safety, and every reason not to do so for performance. Thread safety extends further to any set of statements that are accessing or assigning to a variable independently of any other variable values.
according to the description above, operations like flag = true is always atomic and does not need synchronize.
However, here comes another article that regards the flollowing circumstance as data race:
class DataRaceExample {
static boolean flag = false;//w0
static void raiseFlag() {
flag = true;//w1
}
public static void main(String... args) {
ForkJoinPool.commonPool().execute(DataRaceExample::raiseFlag);
while (!flag);//r_i, where i ∈ [1, k), k may be infinite
System.out.print(flag);//r
}
}
and the author says:
Now, all executions have data races, because the flag is not volatile
It confused me a lot for the conflits between the two articles.
Jack Shirazi is wrong.
Access and update of a primitive variable such as int is atomic, but not synchronized.
Because it is atomic, it can be made fully thread-safe by making it volatile. Without that, other threads running on a different core may see stale values, because the CPU cache hasn't been refreshed.
The point that Jack Shirazi is trying to make is that non-volatile accesses to primitive types other than double and long are guaranteed to be performed atomically according to the JMM. Thus, synchronization is unnecessary to prevent, for example, torn reads and writes in the presence of concurrent accesses.
The confusion arises because his book predates JSR-133 and he uses terms like "automatically synchronized" which is not in line with modern notions of synchronization within the JMM.
In your second example, the loop will either not run or run forever.
The reason for this is that the variable flag is read just once when it is first checked.
If flag is volatile, then it is read from memory each time. This allows another thread to change the value of flag and the loop will see it.
I have been trying to figure out that how immutable objects which are safely published could be observed with stale reference.
public final class Helper {
private final int n;
public Helper(int n) {
this.n = n;
}
}
class Foo {
private Helper helper;
public Helper getHelper() {
return helper;
}
public void setHelper(int num) {
helper = new Helper(num);
}
}
So far I could understand that Helper is immutable and can be safely published. A reading thread either reads null or fully initialized Helper object as it won't be available until fully constructed. The solution is to put volatile in Foo class which I don't understand.
The fact that you are publishing a reference to an immutable object is irrelevant here.
If you are reading the value of a reference from multiple threads, you need to ensure that the write happens before a read if you care about all threads using the most up-to-date value.
Happens before is a precisely-defined term in the language spec, specifically the part about the Java Memory Model, which allows threads to make optimisations for example by not always updating things in main memory (which is slow), instead holding them in their local cache (which is much faster, but can lead to threads holding different values for the "same" variable). Happens-before is a relation that helps you to reason about how multiple threads interact when using these optimisations.
Unless you actually create a happens-before relationship, there is no guarantee that you will see the most recent value. In the code you have shown, there is no such relationship between writes and reads of helper, so your threads are not guaranteed to see "new" values of helper. They might, but they likely won't.
The easiest way to make sure that the write happens before the read would be to make the helper member variable final: the writes to values of final fields are guaranteed to happen before the end of the constructor, so all threads always see the correct value of the field (provided this wasn't leaked in the constructor).
Making it final isn't an option here, apparently, because you have a setter. So you have to employ some other mechanism.
Taking the code at face value, the simplest option would be to use a (final) AtomicInteger instead of the Helper class: writes to AtomicInteger are guaranteed to happen before subsequent reads. But I guess your actual helper class is probably more complicated.
So, you have to create that happens-before relationship yourself. Three mechanisms for this are:
Using AtomicReference<Helper>: this has similar semantics to AtomicInteger, but allows you to store a reference-typed value. (Thanks for pointing this out, #Thilo).
Making the field volatile: this guarantees visibility of the most recently-written value, because it causes writes to flush to main memory (as opposed to reading from a thread's cache), and reads to read from main memory. It effectively stops the JVM making this particular optimization.
Accessing the field in a synchronized block. The easiest thing to do would be to make the getter and setter methods synchronized. Significantly, you should not synchronize on helper, since this field is being changed.
Cite from Volatile vs Static in Java
This means that if two threads update a variable of the same Object concurrently, and the variable is not declared volatile, there could be a case in which one of the thread has in cache an old value.
Given your code, the following can happen:
Thread 1 calls getHelper() and gets null
Thread 2 calls getHelper() and gets null
Thread 1 calls setHelper(42)
Thread 2 calls setHelper(24)
And in this case your trouble starts regarding which Helper object will be used in which thread. The keyword volatile will at least solve the caching problem.
The variable helper is being read by multiple threads simultaneously. At the least, you have to make it volatile or the compiler will begin caching it in registers local to threads and any updates to the variable may not reflect in the main memory. Using volatile, when a thread starts reading a shared variable, it will clear its cache and fetch a fresh value from the global memory. When it finishes reading it, it will flush the contents of its cache into the main memory so that other threads may get the updated value.
This Q is looking for specific details on how exactly Java makes a volatile field visible.
The volatile keyword in Java is used for making a variable "actively" visible to the readers of that variable right after a write operation on it is done. This is one form of happens-before relationship-- makes the results of a write exposed to whoever accessing that memory location of that variable for some use. And when used, makes the read/write operations on that variable atomic-- for long & double as well-- R/W to every other var types are atomic already.
I'm looking to find out what Java does to make a variable value visible after a write operation?
Eg.: The following code is from one of the answers on this discussion:
public class Foo extends Thread {
private volatile boolean close = false;
public void run() {
while(!close) {
// do work
}
}
public void close() {
close = true;
// interrupt here if needed
}
}
Reads and writes to boolean literals are atomic. if the method close() above is invoked, it is an atomic operation to set the value of close as true even if it isn't declared as volatile.
What more volatile is doing in this code is making sure that a change to this value is seen the moment it happens.
How exactly volatile is achieving this?
by giving priority to threads with operations on a volatile variable? if so - how, in thread scheduling, or by making the threads-with-read-operations go look up a flag to see whether there's a writer-thread pending? I'm aware that "A write to a volatile field happens-before every subsequent read of that same field." Is it choosing among the threads, the one(s) that have a write operation on a volatile variable before giving CPU time to threads that only read?
If this is managed in thread scheduling level (which i doubt), then running a thread with a write on a volatile field has a bigger effect than it seems.
How exactly is Java managing visibility of volatile variables?
TIA.
This is the comment from source code of OpenJDK about volatile
// ----------------------------------------------------------------------------
// Volatile variables demand their effects be made known to all CPU's
// in order. Store buffers on most chips allow reads & writes to
// reorder; the JMM's ReadAfterWrite.java test fails in -Xint mode
// without some kind of memory barrier (i.e., it's not sufficient that
// the interpreter does not reorder volatile references, the hardware
// also must not reorder them).
//
// According to the new Java Memory Model (JMM):
// (1) All volatiles are serialized wrt to each other. ALSO reads &
// writes act as aquire & release, so:
// (2) A read cannot let unrelated NON-volatile memory refs that
// happen after the read float up to before the read. It's OK for
// non-volatile memory refs that happen before the volatile read to
// float down below it.
// (3) Similar a volatile write cannot let unrelated NON-volatile
// memory refs that happen BEFORE the write float down to after the
// write. It's OK for non-volatile memory refs that happen after the
// volatile write to float up before it.
//
// We only put in barriers around volatile refs (they are expensive),
// not _between_ memory refs (that would require us to track the
// flavor of the previous memory refs). Requirements (2) and (3)
// require some barriers before volatile stores and after volatile
// loads.
I hope it's helpful.
According to this :
http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile
Java's new memory model does this by
1) prohibiting the compiler and runtime from allocating volatile variables in registers.
2) not allowing the compiler/optimizer to reorder field access from the code. Effectively, this is like acquiring a lock.
3) Forcing the compiler/runtime to flush a volatile variable to main memory from cache as soon as it is written.
4) Marking a cache as invalidated before a volatile field is read.
From the article:
"Volatile fields are special fields which are used for communicating state between threads. Each read of a volatile will see the last write to that volatile by any thread; in effect, they are designated by the programmer as fields for which it is never acceptable to see a "stale" value as a result of caching or reordering. The compiler and runtime are prohibited from allocating them in registers. They must also ensure that after they are written, they are flushed out of the cache to main memory, so they can immediately become visible to other threads. Similarly, before a volatile field is read, the cache must be invalidated so that the value in main memory, not the local processor cache, is the one seen. There are also additional restrictions on reordering accesses to volatile variables. "
...
"Writing to a volatile field has the same memory effect as a monitor release, and reading from a volatile field has the same memory effect as a monitor acquire. In effect, because the new memory model places stricter constraints on reordering of volatile field accesses with other field accesses, volatile or not..."
I'm reading JSR 133 Cookbook and have the following question about memory barriers. An example of inserted memory barriers is in the book, but only writing and reading from local variables is used. Suppose I have the following variables
int a;
volatile int b;
And the code
b=a;
Do I understand correctly that this one line would produce the following instructions
load a
LoadStore membar
store b
The underlying behavior of the JVM is guaranteed only against the volatile variable. It may be possible that two separate threads may have access to different values for variable 'a' even after a thread completes evaluation of the b = a; statement. The JVM only guarantees that access to the volatile variable is serialized and has Happens-Before semantics. What this means is that the result of executing b = a; on two different threads (in the face of a "volatile" value for 'a' (ha ha)) is indeterminate because the JVM only says that the store to 'b' is serialized, it puts no guarantee on which thread has precedence.
More precisely what this means is that the JVM treats variable 'b' as having its own lock; allowing only one thread to read or write 'b' at a time; and this lock only protects access to 'b' and nothing else.
Now, this means different things under different JVMs and how this lock is actually implemented on different machine architectures may result in vastly different runtime behavior for your application. The only guarantee you should trust is what the Java reference manual says, "A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable." For further review see Dennis Byrne's excellent article for some examples of how different JVM implementations deal with this issue.
Happens-Before semantics are not very interesting in the provided example because an integer primitive doesn't provide much opportunity for the kind of instruction reordering that volatile was intended (in part) to remedy. A better example is this:
private AnObjectWithAComplicatedConstructor _sampleA;
private volatile AnObjectWithAComplicatedConstructor _sampleB;
public void getSampleA() {
if (_sampleA == null) {
_sampleA = new AnObjectWithAComplicatedConstructor();
}
return _sampleA;
}
public void getSampleB() {
if (_sampleB == null) {
_sampleB = new AnObjectWithAComplicatedConstructor();
}
return _sampleB;
}
In this example field '_sampleA' has a serious problem; in a multithreaded situation it is very possible that '_sampleA' may be in the process of being initialized in one thread at the same time another thread attempts to use it leading to all sorts of sporatic and very, very difficult to duplicate bugs. To see this consider thread X to execute the 'new' byte code instruction statement of the new in getSampleA() and then stores the (yet-to-be-initialized) result in field '_sampleA'. Thread X is now paused by the JVM and thread Y starts executing getSampleA() and sees that the '_sampleA' is not null; which uninitialized value is then returned and thread Y now starts calling methods on the resulting instance causing all sorts of problems; which will, of course, only appear in production, at odd hours, and under heavy service loads.
The worse case for field _sampleB is that it may have multiple threads initializing individual instances; all but one of which will eventually be discarded. Code like this should be wrapped in a "synchronized" block but the volatile keyword will do the trick because it requires that the value finally stored in '_sampleB' has Happens-Before semantics which means that the stuff to the right of the equals sign is guaranteed to be complete when the stuff on the left hand side of the equals sign is performed.