I have a variable that I need to set the value of that I want thread visible. I have no idea what thread is doing the reading a writing.
The variable is only ever set once so by setting it as volatile I prevent the variable value from being read from the CPU cache (or so is my understanding). Write once, read many.
I am unable to get this variable into a constructor to use final.
My rough flow is:
thread 1: set value x
thread 1: fire notification to say x is ready.
thread 2: read x.
My understanding is that I can do the following:
public void setX(int value) {
Object o = new Object();
synchronized(o) {
this.x = value;
}
}
And because of the happens-before principle, the value will be written out to memory. Is that correct?
Don't set it to volatile. As a thumb rule, use volatile if the value of that variable is changing and multiple threads read / write to that variable.In your case you want the reads to be cached. because the value of x won't change. Using volatile will reduce performance In your case, you will just have to ensure that the set() happens before the get() . Which will actually happen because unless someThread notifies the other thread, the other thread will not read the value of x.
PS : I am assuming that the other thread(s) will not read value of x unless notified. Let me know if I got your question wrong.
Synchronizing on the object created in the method is pointless.
How you notify() all reading threads is a question you will need to answer yourself - do you intend to have them wait()ing for this notification?
I would suggest to return null or throw from the getter if the value is not set yet instead...
Related
This question already has an answer here:
Does the Java Memory Model guarantee visibility of intra-thread writes?
(1 answer)
Closed 2 years ago.
The code is simple.
// not annotated with volatile
public static int I = 0;
public static int test(){
I = 1;
return I;
}
There is a thread that invokes the method test.
Is it possible the method test will return the value '0'?
In other words, the reading of a shared variable maybe not see the modifying by the same thread.
update
The question just very simple, but I make its obscurity, I'm really sorry about it.
The a thread means a single thread.
And the question is duplicated with it.
Any answer that does not explain in terms on java language specification is only partially correct, if correct at all.
You need to make a clear distinction between actions that happens within a single thread and are tied together by program order and that in turn creates a happens-before connection, specifically via:
If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).
That rule tells you that if you think about this code in single threaded world, it will always print 1.
And on the other hand, actions that create synchronizes with connections across different threads, and implicitly those create happens-before, via:
If an action x synchronizes-with a following action y, then we also have hb(x, y).
In your case, I is a plain field, as such every operation related to it is a plain store and/or a plain load. Such stores and loads do not created any connections at all according to the JLS. As such some thread that reads I can always read it as 0 if there is a writing thread involved.
No, it will be 1 if no other thread is involved but the one that will invoke the method.
chrylis -cautiouslyoptimistic's answer is worth reading for an alternative scenario as well.
Two reasons:
I is just altered by its owner, and if the other thread just calls test(), there's no option for it to get a 0 as I's value.
The second thread won't read Class.I's value, but the result of the test() method. The assignation I=1 happens before the return so is guaranteed to offer the latest updated value (which has only been updated by the owner, once).
Yes, it is possible for the test method to return 0, if another thread writes to i between the assignment and the return statement:
Thread 1: assign i = 1
Thread 2: assign i = 0
Thread 1: return i (sees the 0 that Thread 2 just wrote)
To prevent this, all access to i, reads and writes, would need to be synchronized on the same condition. Making i volatile is not sufficient to prevent threads from taking turns modifying it.
Note that it's not that Thread 1 "does not see" the i = 1 write; that is guaranteed, because all statements logically execute in program order. However, another thread might change the value after that write happens but before Thread 1 reads it.
There is an article about volatile using in ibm,and the explanation confused me,below is a sample in this article and its explanation:
public class BackgroundFloobleLoader {
public volatile Flooble theFlooble;
public void initInBackground() {
// do lots of stuff
theFlooble = new Flooble(); // this is the only write to theFlooble
}
}
public class SomeOtherClass {
public void doWork() {
while (true) {
// do some stuff...
// use the Flooble, but only if it is ready
if (floobleLoader.theFlooble != null)
doSomething(floobleLoader.theFlooble);
}
}
}
Without the theFlooble reference being volatile, the code in doWork() would be at risk for seeing a partially constructed Flooble as it dereferences the theFlooble reference.
How to understand this?Why without volatile,we may use a partially constructed Flooble object?Thanks!
Without the volatile you could see a partially constructed object. E.g. consider this Flooble object.
public class Flooble {
public int x;
public int y;
public Flooble() {
x = 5;
y = 1;
}
}
public class SomeOtherClass {
public void doWork() {
while (true) {
// do some stuff...
// use the Flooble, but only if it is ready
if (floobleLoader.theFlooble != null)
doSomething(floobleLoader.theFlooble);
}
public void doSomething(Flooble flooble) {
System.out.println(flooble.x / flooble.y);
}
}
}
Without volatile the method doSomething is not guaranteed to see the values 5 and 1 for x and y. It could see for instance x == 5 but y == 0, leading to division by zero.
When you execute this operation theFlooble = new Flooble(), three writes occur:
tmpFlooble.x = 5
tmpFlooble.y = 1
theFlooble = tmpFlooble
If these writes happen in this order everything is ok. But without the volatile the compiler is free to reorder these writes and perform them as it wishes. E.g. first point 3 and then points 1 and 2.
This actually happens all the time. The compiler really does reorder the writes. This is done to increase performance.
The error can easily happen in the following way:
Thread A executes initInBackground() method from class BackgroundFloobleLoader. The compiler reorders the writes so before executing the body of Flooble() (where x and y are set), the thread A first executes theFlooble = new Flooble(). Now, theFlooble points to a flooble instance, whose x and y are 0. Before thread A continues, some other thread B executes method doWork() of class SomeOtherClass. This method calls method doSomething(floobleLoader.theFlooble) with the current value of theFlooble. In this method theFlooble.x is divided by theFlooble.y resulting in division by zero. Thread B finishes due to uncaught exception. Thread A continues and sets theFlooble.x = 5 and theFlooble.y = 1.
This scenario of course won't happen on every run, but according to the rules of Java, can happen.
When different threads access your code, any thread can perform modifications on the state of your object, which means that when other threads access it, the state may not be as it should.
From the oracle documentation:
The Java programming language allows threads to access shared
variables. As a rule, to ensure that shared variables are
consistently and reliably updated, a thread should ensure that it has
exclusive use of such variables by obtaining a lock that,
conventionally, enforces mutual exclusion for those shared variables.
The Java programming language provides a second mechanism, volatile
fields, that is more convenient than locking for some purposes.
A field may be declared volatile, in which case the Java Memory Model
ensures that all threads see a consistent value for the variable.
source
Which means the value of this variable will never be cached thread-locally, all reads and writes will go straight to "main memory"
For example picture thread1 and thread2 accessing the object:
Thread1 access the object and stores it in its local cache
Trhead2 modifies the object
Thread1 accesses the object again, but since it is still in its cache, it doesn't access the updated state by thread2.
Look at it from the point of view of the code that does this:
if (floobleLoader.theFlooble != null)
doSomething(floobleLoader.theFlooble);
Clearly, you need a guarantee that all of the writes performed by new Flooble() are visible to this code before theFlooble could possibly test as != null. Nothing in the code without volatile provides this guarantee. So you need a guarantee you don't have. Fail.
Java provides several ways to get the guarantee you need. One is by use of a volatile variable:
... any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable. This means that changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change. -- Docs
So putting a write to a volatile in one thread and a read to a volatile in the other establishes precisely the happens-before relationship we need.
I doubt there is such a thing as partially constructed objects in Java. Volatile guarantees that every thread will see a constructed object. Since volatile works like a tiny synchronized block on the referenced object you would end up with a NPE if theFlobble == null. Maybe that is what they mean.
Objects encapsulate a lot of things: variables, methods, etc. and these take time to come into existence inside a computer. In Java, if any variable is declared volatile then all reads and writes to it is atomic. So if a variable referencing an object is declared volatile then access to its members is allowed only when it fully loads in your system (how do you read or write to something that isn't there at all?)
Just to make sure I understand the concepts presented in java concurrency in practice.
Lets say I have the following program:
public class Stuff{
private int x;
public Stuff(int x){
this.x=x;
}
public int getX(){return x;}
}
public class UseStuff(){
private Stuff s;
public void makeStuff(int x){
s=new Stuff(x);
}
public int useStuff(){
return s.getX();
}
}
If I let multiple threads to play with this code, then I'm not only in trouble because s might be pointing to multiple instances if two or more threads are entering to the makeStuff method, but even if just one thread creates a new Stuff, then an other thread who is just entered to useStuff can return the value 0 (predefined int value) or the value assigned to "x" by its constructor.
That all depends on whether the constructor has finished initializing x.
So at this point, to make it thread safe I must do one thing and then I can choose from two different ways.
First I must make makeStuff() atomic, so "s" will point to one object at a time.
Then I either make useStuff synchronized as well which ensures the I get back the Stuff object x var only after its constructor has finished building it, OR i can make Stuff's x final, and by this the JMM makes sure that x's value will only be visible after it has been initialized.
Do I understand the importance of final fields in the context of concurrency and JMM?
Do I understand the importance of final fields in the context of concurrency and JMM?
Not quite. The spec writes:
final fields also allow programmers to implement thread-safe immutable objects without synchronization. A thread-safe immutable object is seen as immutable by all threads, even if a data race is used to pass references to the immutable object between threads. This can provide safety guarantees against misuse of an immutable class by incorrect or malicious code
If you make x final, this guarantees that every thread that obtains a reference to a Stuff instance will observe x to have been assigned. It does not guarantee that any thread will obtain such a reference.
That is, in the absence of synchronization action in useStuff(), the runtime is permitted to satisfy a read of s from a register, which might return a stale value.
The cheapest correctly synchronized variant of this code is declaring s volatile, which ensures that writes to s happen-before (and are therefore visible to) subsequent reads of s. If you do that, you need not even make x final (because the write to x happens-before the write of s, the read of s happens-before the read of x, and happens-before is transitive).
Some answers claim that s can only refer to one object at a time. This is wrong; because there is no memory barrier, different threads can have their own notion about the value of s. In order for all threads to see a consistent value assigned to s, you need to declare s as volatile, or use some other memory barrier.
If you do this, you won't need to declare x as final for the correct value to be visible to all threads (but you might still want to; fields shouldn't be mutable without a reason). That's because the initialization of x happens-before the assignment of s in "source code order," and the write of the volatile field s happens-before other thread reads that value from s. If you subsequently modified the value of a non-final field x, however, you could run into trouble because the modification isn't guaranteed to be visible to other threads. Making Stuff immutable would eliminate that possibility.
Of course, there's nothing to stop threads from clobbering the value assigned to s, so different threads could still see different values for x. This isn't really a threading issue though. Even a single thread could write and then read different values of x over time. But preventing this behavior in a multi-threaded environment requires atomicity, that is, checking to see whether s has a value and assigning one if not should appear as one indivisible action to other threads. An AtomicReference would be the best solution, but the synchronized keyword would work too.
What are you trying to protect by making things synchronized? Are you concerned that thread A will call makeStuff and then thread B will call getStuff afterwards and the value won't be there? I'm not sure how synchronizing any of this will help that. Depending on what problem you are trying to avoid, it might be as simple as marking s as volatile.
I'm not sure what you're doing there. Why are you trying to create an object and then assign it to a field? Why save it if it can be overwritten by other call to makeStuff? It seems like you use UseStuff both as an proxy and as a factory to your actual Stuff model object. You better separate the two:
public class StuffFactory {
public static Stuff createStuff(int value) {
return new StuffProxy(value);
}
}
public class StuffProxy extends Stuff {
// Replacement for useStuff from your original UseStuff class
#Override
public int getX() {
//Put custom logic here
return super.getX();
}
}
The logic here is that each thread is responsible for creation of their own Stuff objects (using the factory) so concurrent access no longer an issue.
After reading a bunch of questions / articles on this topic there is still one thing unclear to me.
From what I understand (and please correct me if I'm wrong) is that the value of a variable can be cached locally to a thread so if one thread updates the value of that variable this change may not be visible to another thread. The use of volatile then is to essentially force all threads to read the value of the variable from the same location. Furthermore, all literature on this topic states that synchronizing on that variable will have the same effect.
My problem is that nothing that I've read ever explicitly states that synchronizing on a different variable will cause this same behavior but frequently provides a code example stating that in the following two cases the value that is read from the variable will be up to date :
volatile int x;
...
int y = x;
and
final Object lock = new Object();
int x;
...
synchronized(lock) {
int y = x;
}
The question is then: is it the case that synchronizing on any arbitrary variable will force every variable access within the synchronized block to access the most up to date value of that variable?
is it the case that synchronizing on any
arbitrary variable will force every variable access within the
synchronized block to access the most up to date value of that
variable?
You can synchronize on any variable for a read so long as the write of that variable was done under synchronization of the same variable.
In your example, so long as something like the following happens then all writes that occurred prior to the write of x will be visible after subsequent read:
synchronized(lock){
x = 10;
}
So to your earlier point:
...nothing I've read ever explicitly states that synchronizing on a different
variable will cause this same behavior...
That is because it doesn't offer the same behavior. The happens-before relationship occurrs on a few occasions, two important ones in your case are
Write and subsequent read of the same volatile variable
The exit and subsequent enter of a monitor on the same object
There is an enlightening article here where it is mentioned:
In the Java Memory Model a volatile field has a store barrier inserted after a write to it and a load barrier inserted before a read of it. ...
Note that there is nothing specific to what field is being accessed. This means that accessing any volatile field generates a barrier for all cached variables.
Synchronising has similar functionality.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Thread safety in Java class
I'm reading Java concurrency in Practice, and I've come to an example that puzzles me.
The authors state that this class is not threadsafe
public class MutableInteger {
private int number;
public int getInt() {
return number;
}
public void setInt(int val) {
number = val;
}
}
And they also state that synchronizing only one method (the setter for example) would not do; you have to syncronize both.
My question is: Why? Wouldn't synchronizing the setter just do?
Java has a happens before/happens after memory model. There needs to be some common concurrent construct (e.g. synchronized block/method, lock, volatile, atomic) on both the write path and the read path to trigger this behaviour.
If you synchronize both methods you are creating a lock on the whole object that will be shared by both the read and write threads. The JVM will ensure that any changes that occur on the writing thread that occur before leaving the (synchronized) setInt method will be visible to any reading threads after they enter the (synchronized) getInt method. The JVM will insert the necessary memory barriers to ensure that this will happen.
If only the write method is synchronized then changes to the object may not be visible to any reading thread. This is because there is no point on the read path that the JVM can use to ensure that the reading thread's visible memory (cache's etc.) are in line with the writing thread. Make the getInt method synchronized would provide that.
Note: specifically in this case making the field 'number' volatile would give the correct behaviour as volatile read/write also provides the same memory visibility behaviour in the JVM and the action inside of the setInt method is only an assignment.
It's explained in the book before the sample (page 35):
"Synchronizing only the setter would not be sufficient: threads calling get would still be able to see stale values."
Stale data: When the reader thread examines ready, it may see an out-of-date value. Unless synchronization is used every time a variable is accessed, it is possible to see a stale value for that variable. Worse, staleness is not all-or-nothing: a thread can see an up-to-date value of one variable but a stale value of another variable that was written first.
If you only Synchronize the setter method, you could only guarantee the attribute would not be amended incorrectly, but you could not be sure it is stale value when you try to read the variable.
because number is not volatile, and getInt() is not synchronized, getInt() may return stale values. For more information, read about the java memory model.