Reputation: 180
its a related question to this one: java: using volatile at one variable VS each variable
i have one or more different objects. i want to change some state in it and then i want to make that state visible to other threads.
For performance reasons i dont want to make each member variable in that objects volatile. And sometimes i want to use these objects in a single thread application. So in that case the volatile would be also bad.
So i had the following:
//these following mehtods change some internal variable state. These variables are not volatile or synchronized
boolean volatile memoryFlusher=false;
Thread1:
obj1->changeSomeState();
obj1->changeMoreState();
obj2->alsoSomeStateChange();
//and now i want to make that state visible to others
memoryFlusher=false; //volatile write
Thread2:
boolean tmp=memoryFlusher; // volatile read but variable is not used again
obj1->getState();
obj2->getState();
So till now its more or less the same to my related question i linked at the beginning.
So now i want to ask the following:
My memoryFlusher is not optimzed away? (unanswerd in my other question) Each volatile write/read flushes all memoryState of ALL? other (also none-volatile-)variables?
And now the really new question:
is that a good design, i do there? Cause i didnt saw any code anywhere like this, i posted here.
Should i program my Progamm in a other way? Is there a other best practise to increase the performance and getting visibilty? Is there other best practise in the program-design view, not having doing something like this?
Edit:
the state i change is unreleated. So i want with that memory-variable one memoryflusher, and no lock mechanism. It should replace a lot of single volatile variable to one. somewhere i dont need that explicit volatile memoryFlushing cause i use a synchronized, for example
synchronized(x)
{
...
obj1->stateChange() //if internally is used a volatile, then i have a volatile memory flush and later the synchronized-end memory-flush, i guess (is that right?)
...
}
That would be one example, where it could be useful?!
summary: But is that correct, in that way i think using that memoryFlushing?
Upvotes: 3
Views: 115
Reputation: 40256
My memoryFlusher is not optimzed away?
No, the write to and read from memoryFlusher
will not be optimized away.
Each volatile write/read flushes all memoryState of ALL
Yes, it will synchronize memory to both threads. However, it only works if you can detect the change from one thread to another.
In your example, you read memoryFlusher
, but memoryFlusher
is false
on initialization. How do you know Thread-1
actually wrote to it? What if, Thread-1 is at this line obj1 -> changeMoreState
, and Thread-2 reads memoryFlusher
. Both values would be false
here and so you don't know if Thread-1 actually completed.You are out of sync as you haven't established your happens-before ordering.
To correct your code, you should write true
to the memoryFlusher
field and Thread-2 should only continue if memoryFlusher
is true. This effectively establishes your ordering, but it also makes your code more confusing.
I'd suggest using a StampedLock instead of trying this. The StampedLock gives you really fast reads when writes are not going to be frequent.
Upvotes: 2
Reputation: 59144
Your volatile reads and writes are not optimized away, but I don't see any use for this code. That's probably why you don't see it elsewhere. You didn't say what you expect from it, though, so who knows?
It looks like you want to make sure that Thread2 reliably reads the state changes made by Thread1. Well, that works only if you are sure that the code in Thread2 actually runs after the code in Thread1.
How do you know that that is the case?
I suggest that if there is really any way you can be sure that the Thread2 code happens after the Thread1 code, then there is already a memory barrier in place that establishes this fact, and renders your volatile variable unnecessary.
Upvotes: 2