Reputation: 2183
From the book "Effective java" i have following famous code of stopping one thread from another
public class StopThread {
private static boolean stopRequested;
private static synchronized void requestStop() {
stopRequested = true;
}
private static synchronized boolean stopRequested() {
return stopRequested;
}
public static void main(String[] args)
throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!stopRequested()) {
i++;
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
requestStop();
}
}
A line is written there that is "synchronization has no effect unless both read and write
operations are synchronized."But it is clear that if we don't use synchronized
keyword with method requestStop
the code will work fine,i.e,it terminates nearly after 1 second which is desired.One thing more here is that if we don't synchronize both the method we will(most probably) go into infinite loop because of code optimization.So my questions are:-
1.How and in what scenario things can go wrong if we don't synchronize 'stopRequested' method?Although here if we don't synchronize it,the program runs as desired,i.e,it terminates nearly in 1sec.
2.Does synchronized
keyword enforces the VM to stop optimization each time?
Upvotes: 2
Views: 443
Reputation: 370
Just make stopRequested volatile. Then method stopRequest does not have to be synchronized, because it does not change anything.
Upvotes: 0
Reputation: 1685
1.How and in what scenario things can go wrong if we don't synchronize 'stopRequested' method?Although here if we don't synchronize it,the program runs as desired,i.e,it terminates nearly in 1sec.
Things can go wrong if JVM decides to optimize the code within the run method of your backgroundThread. The read of stopRequested() can be reordered for optimization by JVM because of which it may never call the stopRequested() method again. But these days almost all JVM implementations take care of this and hence without making stopRequested as synchronized your code will still run fine. Also point to be noted here is that if you donot make stopRequested synchronized then the change done to stopRequested boolean variable may not be seen immediately by other non synchronized threads. Only if you used synchronization can the other threads immediately detect any change as an entry into synchronized method clears the cache and loads the data from the memory fresh. This immediate detection of memory changes is important in a highly concurrent system
2) Does synchronized keyword enforces the VM to stop optimization each time?
Synchronized keyword doesnot enforce VM to stop optimization but it makes it to adhere to the things listed below. VM can still do an optimization but it has to take care of the below things. Synchronization effectively does the following things:-
It guarantees happens before relationship. If one action happens-before another, then the first is visible to and ordered before the second.
It guarantees memory visibility that is all the modifications done within the block which may be cached are immediately flushed before the exit of synchronization block which results in any other synchronized thread to see the memory updates immediately. This will be important in case of highly concurrent systems.
Upvotes: 1
Reputation: 36304
1.How and in what scenario things can go wrong if we don't synchronize 'stopRequested' method?
Assume if one thread is writing (updating) the field stopRequested
, now before the first thread updates the value of stopRequested
from requestStop(), another thread can read the value of stopRequested
by calling stopRequested()
(if stopRequested()
was not synchronized. Thus it would not get the updated value.
2.Does synchronized keyword enforces the VM to stop optimization each time? Not always, Escape Analysis implemented from JDK6U23 also plays a part in this. Synchronization creates a memory barrier which ensures a happens-before relationship. i.e, any block of code executed after a synchronized block is sure to have the updated value (changes made earlier are reflected).
Statements can be executed out-of-order within a synchronized block to improve efficiency provided the happens-before holds good. On the other hand a synchronized block can be removed by the JVM if it determines that the block can be accessed only by a single thread.
Upvotes: 1
Reputation: 96414
Changes by a thread to a variable are not necessarily seen right away by other threads. Using synchronized here makes sure that the update by one thread is visible to the other thread.
1) The change would possibly not become visible to the other thread. In the absence of synchronization or volatile or atomic fields there's no assurance when the other thread will see the change.
2) The synchronized keyword helps the VM decide on limits on instruction reordering and on what the VM can optimize.
Testing this on your machine will not necessarily display the same results as using a server with more processors. Different platforms may do more optimizing. So just because it works on your machine doesn't necessarily mean it's ok.
Upvotes: 1