understanding synchronized in java - java

Why usually threading samples put so many code in synchronized block. According to my understanding in following case synchronized is used just for locking b for wait and notify:
Main class ThreadA :
class ThreadA {
public static void main(String [] args) {
ThreadB b = new ThreadB();
b.start();
synchronized(b) {
try {
System.out.println("Waiting for b to complete...");
b.wait();
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.total);
System.out.println(Thread.currentThread().getName());
}
}
}
and class ThreadB:
class ThreadB extends Thread {
int total;
public void run() {
synchronized(this)
{
System.out.println();
for(int i=0;i<100;i++)
{
System.out.println(Thread.currentThread().getName());
total += i;
}
notify();
}
}
}
What will change if I put just wait and notify in synchronized block:
class ThreadA {
public static void main(String [] args) {
ThreadB b = new ThreadB();
b.start();
try {
System.out.println("Waiting for b to complete...");
synchronized(b) { b.wait();}
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.total);
System.out.println(Thread.currentThread().getName());
}
}

According to my understanding in following case synchronized is used just for locking b for wait and notify
Your understanding is wrong.
synchronized is also used for:
Mutual exclusion, to ensure that only one thread executes code "guarded" by a particular monitor at a time
Ensuring memory access across threads is correct (that one thread sees changes made by another thread)
What will change if I put just wait and notify in synchronized block:
In this particular case, it will make a difference based on a race condition - in the original code, if the new thread starts executing before the synchronized block is reached in the original thread, it won't get as far as "Waiting for b to complete" until the second thread has finished... at which point it will block forever in wait.
Note that it's a really bad idea to wait on Thread monitors, as wait/notify is used internally by Thread.
In short, the example you've used is a bad one to start with in various ways - but synchronization is used for more than just wait/notify.

Please note that total += i is not an atomic operation in Java. So you have to sync also this construct.
You also have not to sync notify() and wait() because their locks are handled internally.

Expanding on the answer by #sk2212, the increment operation is not atomic, but there is an equivalent atomic operation provided in high-level concurrency primitives.

Related

Can a java thread waiting with wait() ,notify itself?

I came across the following e example to implement custom suspend and wait from some website.
// Suspending and resuming a thread the modern way.
class NewThread implements Runnable {
String name; // name of thread
Thread t;
boolean suspendFlag;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
suspendFlag = false;
t.start(); // Start the thread
}
// This is the entry point for thread.
public void run() {
try {
for (int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
synchronized(this) {
while (suspendFlag) {
wait();
}
}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
void mysuspend() {
suspendFlag = true;
}
synchronized void myresume() {
suspendFlag = false;
notify();
}
}
class SuspendResume {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.mysuspend();
System.out.println("Suspending thread One");
Thread.sleep(1000);
ob1.myresume();
...................
I am more concerned about the ob1.mysuspend() and ob1.myresume() calls. When my suspend is called then ob1 will be placed into the blocking queue associated with the runnable object it is using. When ob1 calls myresume, then how does it work as ob1 is already in waiting queue for the same object, can the waiting object enters another synchronised method and then signals notify to itself?How does this work?What am I missing?
The thread is written so that while an instance of NewThread is running, another thread can call mysuspend to suspend that running thread. Again, a thread other than the suspended thread calls myresume to resume the suspended thread.
There also appears to be a data race because mysuspend writes to suspendFlag without any synchronization. That means, the thread that needs to be suspended may not see that write immediately. mysuspend must be declared synchronized, or suspendFlag must be volatile.
This code is flat out broken.
Straight up broken: JMM violation
The mysuspend method (which should be named mySuspend, by the way) updates a field that is then read from another thread, and isn't synchronized. This is an error - and a really nasty one because you cannot reliably test that it is an error. The Java Memory Model (JMM) states that any write to a field may be observable or not, at the discretion of the JVM implementation, unless a so-called Happens-Before/Happens-After relationship is established (there are many ways to do it; usually you do so via synchronized, volatile, or some other concurrency tool built on these primitives, such as the latches and queues in the java.util.concurrent package).
You do not establish such a relationship here, meaning, that suspendFlag = true results in a schroedingers cat variable: The other thread that reads this field may read true or false, the JVM gets to decide what you see. Hence: A bug, and, untestable. bad. Any field that is read/written to by multiple threads needs to be written extremely carefully.
Mark that method synchronized, that's a good first step.
Wait and Notify
You've got it flipped around: You must in fact hold the synchronized lock on x when you invoke wait on x (here, x is this).
To call x.wait() (you are calling this.wait(), effectively), you must first be in a synchronized(x) block. Once the wait 'goes through', the code releases the lock (other synchronized(x) blocks can run). To invoke x.notify() you must also hold that lock.
wait does not return until the lock is re-established.
In other words:
public void foo() {
wait();
}
will fail at runtime. Try it. Guaranteed exception. In the mean time, this:
public void foo() {
synchronized (this) {
// code before wait
wait();
// code after wait
}
}
is executed as if it is written like this:
public void foo() {
synchronized (this) {
// code before wait
release_lock(this);
this.wait();
acquire_lock(this);
// code after wait
}
}
Where acquire_lock is guaranteed to actually take a while (because by definition whatever invoked notify() to wake you up is currently holding it! So wait is always a two-hit thing: You need to be both notified AND the lock needs to be reacquired before your code will continue). Except, of course, acquire_lock and release_lock don't exist, and unlike this hypothetical code, wait() is more atomic than that.

Significance of use of keyword synchronized in the following code

I was reading multi threading in Java from the book Java The Complete Reference by Herbert Schildt. I came across following code [Pg. 252, 7th ed.] that explained the usage of wait() and notify() to suspend and resume threads in modern Java. My question is regarding the significance of the keyword synchronization at two places in following code (in run() method of class NewThread):
// Suspending and resuming a thread the modern way.
class NewThread implements Runnable {
String name;
Thread t;
boolean suspendFlag;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
suspendFlag = false;
t.start();
}
// This is the entry point for thread.
public void run() {
try {
for (int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
synchronized (this) { //First doubt here
while (suspendFlag) {
wait();
}
}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
void mysuspend() {
suspendFlag = true;
}
synchronized void myresume() { //Second doubt here
suspendFlag = false;
notify();
}
}
class SuspendResume {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.mysuspend();
Thread.sleep(1000);
ob1.myresume();
ob2.mysuspend();
Thread.sleep(1000);
ob2.myresume();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
//some code
}
My doubt here: I know about the use of keyword synchronization i.e. allowing only one thread to enter a synchronized method on the same object but here we have two threads running on two different objects. So what is the significance of both synchronization keywords used in above code.
I tried running the above code by removing the synchronized keyword at each place differently and simultaneously. I am getting the same error: java.lang.IllegalMonitorStateException: current thread is not owner different number of times and at different line numbers depending upon if I remove both or only one (and which one) synchronization keyword. I looked for the above error and found an explanation for it here but still couldn't connect the answer to my doubt.
The problem that synchronized solves is, it allows the two threads to have a consistent view of the shared suspendFlag variable.
In some real program, a thread might set other shared variables before setting susependFlag=false. If synchronized was not used, then the waiting thread could wake up, and see suspendFlag==false, but not see the other variables set. Or worse, it could see some of them set, but not others.
Without synchronization, Java does not guarantee that different threads will see variables updated in the same order.
I am getting the same error: java.lang.IllegalMonitorStateException: current thread is not owner.
The Java library is trying to help you by forcing you to use synchronized before it will allow you to use wait() and notify(). The rule is simple: You can only call o.wait() or o.notify() or o.notifyAll() from code that is inside a synchronized(o) block. If you break that rule, then the library throws the exception.
When your code calls o.wait() the wait() call temporarily unlocks the monitor lock so that the other thread will be able to synchronize on o and call o.notify(). The o.wait() call is guaranteed to re-lock o before it returns.

Thread deadlock avoidance

I want to know if it's authorized to avoid Thread deadlocks by making the threads not starting at the same time? Is there an other way to avoid the deadlocks in the following code?
Thanks in advance!
public class ThreadDeadlocks {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
public static void main(String args[]) {
ThreadDemo1 t1 = new ThreadDemo1();
ThreadDemo2 t2 = new ThreadDemo2();
t1.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
t2.start();
}
private static class ThreadDemo1 extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println("Thread 1: Holding lock 1...");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
}
}
private static class ThreadDemo2 extends Thread {
public void run() {
synchronized (Lock2) {
System.out.println("Thread 2: Holding lock 2...");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (Lock1) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}
}
There are two ways to get a deadlock:
Lock escalation. For example, a thread holding a shareable read
lock tries to escalate to an exclusive write lock. If more than one
thread holding a read lock tries to escalate to a write lock, a
deadlock results. This doesn't apply to what you're doing. (Offhand, I don't even know if it's possible to escalate a lock in Java.)
Unspecified lock order. If thread A locks object 1, then tries to lock object 2, while thread B locks object 2 then tries to lock object 1, a deadlock can result. This is exactly what you're doing.
Those are the only ways to get a deadlock. Every deadlock scenario will come down to one of those.
If you don't want deadlocks, don't do either of those. Never escalate a lock, and always specify lock order.
Those are the only ways to prevent deadlocks. Monkeying around with thread timing by delaying things is not guaranteed to work.
As the other mentioned, delays won't help because threads by their nature have unknown start time. When you call start() on a thread, it becomes runnable, but you cannot know when it will be running.
I'm assuming this is just demo code, so you already know that playing with sleeps is not guaranteed to work (as stressed in other answers).
In your demo code I see two options to try avoid the deadlock:
Remove any sleep within the body of the functions executed by the threads and just put a single, long enough, sleep between the start of the two threads; in practical terms, this should give enough time to the first thread to be scheduled and complete its work, then the second thread will acquire both locks without contention. But, you already know, scheduling policies are not under your control and this is not guaranteed to work at all.
Do acquire locks in the same order in both threads, without using any sleep at all, i.e.
synchronized (Lock1) {
synchronized (Lock2) {
// ...
}
}
This is guaranteed to remove any possible deadlock, because the first thread to acquire Lock1 will gain the possibility to complete its work while blocking the other thread until completion.
UPDATE:
To understand why acquiring locks in the same order is the only guaranteed way to avoid deadlock, you should recall what's the whole purpose of locks.
A thread is said to own a lock between the time it has acquired the lock and released the lock. As long as a thread owns a lock, no other thread can acquire the same lock. In fact, the other thread will block when it attempts to acquire the same lock.
Every object in Java has an intrinsic lock associated with it. The synchronized statement let you automatically acquire the intrinsic lock of the specified object and release it after code execution.
No, starting threads at different times is not a way to avoid deadlocks - in fact, what you'd be trying with different start times is a heuristic to serialize their critical sections. ++ see why at the and of this answer
[Edited with a solution]
Is there an other way to avoid the deadlocks in the following code?
The simplest way is to acquire the locks in the same order on both threads
synchronized(Lock1) {
// do some work
synchronized(Lock2) {
// do some other work and commit (make changes visible)
}
}
If the logic of your code dictates you can't do that, then use java.util.concurrent.locks classes. For example
ReentrantLock Lock1=new ReentrantLock();
ReentrantLock Lock2=new ReentrantLock();
private static class ThreadDemo1 extends Thread {
public void run() {
while(true) {
Lock1.lock(); // will block until available
System.out.println("Thread 1: Holding lock 1...");
try {
// Do some preliminary work here, but do not "commit" yet
Thread.sleep(10);
} catch (InterruptedException e) {
}
System.out.println("Thread 1: Waiting for lock 2...");
if(!Lock2.tryLock(30, TimeUnit.MILLISECOND)) {
System.out.println("Thread 1: not getting a hold on lock 2...");
// altruistic behaviour: if I can't do it, let others
// do their work with Lock1, I'll try later
System.out.println("Thread 1: release lock 1 and wait a bit");
Lock1.unlock();
Thread.sleep(30);
System.out.println("Thread 1: Discarding the work done before, will retry getting lock 1");
}
else {
System.out.println("Thread 1: got a hold on lock 2...");
break;
}
}
// if we got here, we know we are holding both locks
System.out.println("Thread 1: both locks available, complete the work");
// work...
Lock2.unlock(); // release the locks in the reverse...
Lock1.unlock(); // ... order of acquisition
}
}
// do the same for the second thread
++ To demonstrate why delays in starting the threads at different times is not a foolproof solution, think if you can afford to delay one of the threads by 10 seconds in the example below. Then think what will you do if you don't actually know how long to wait.
private static class ThreadDemo1 extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println("Thread 1: Holding lock 1...");
try {
// modelling a workload here:
// can take anywhere up to 10 seconds
Thread.sleep((long)(Math.random()*10000));
} catch (InterruptedException e) {
}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
}
}
private static class ThreadDemo2 extends Thread {
public void run() {
synchronized (Lock2) {
System.out.println("Thread 2: Holding lock 2...");
try {
// modelling a workload here:
// can take anywhere up to 10 seconds
Thread.sleep((long)(Math.random()*10000));
} catch (InterruptedException e) {
}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (Lock1) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}

Wait-Notify synchronized by the same object doesn't work

I made this sample to understand how Wait-Notify works:
public class WaitingTest implements Runnable {
Thread b = new Thread();
int total;
public static void main(String[] args){
WaitingTest w = new WaitingTest();
}
public WaitingTest(){
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + total);
}
}
#Override
public void run(){
synchronized(b){
for(int i=0; i<100 ; i++){
total += i;
System.out.println(total);
}
b.notify();
}
}
}
But I'm stuck here for hours and I can't understand why it's not quite working. My output should be more than 0, but its always zero...I was wondering if its becuase of the usage of different threads, but Im not really sure..What am I missing?
I think you have some serious holes in your understanding. You've declared a Thread
Thread b = new Thread();
and started it in the constructor
b.start();
That Thread will start and die right away since it has no Runnable attached to it.
It just so happens that when a Thread dies, it calls notify() on itself and since you are synchronized on that same Thread object, your wait()ing thread will be awoken. You also have a race here. If the Thread ends before the main thread reaches the wait(), you will be deadlocked.
Also, there is no reason for run() to be called, which is why total remains 0.
Any object can be synchronized on, it doesn't have to be a Thread. And since Thread has that weird behavior of notify()ing itself, you probably shouldn't use it.
You should go through both the Thread tutorials and the synchronization tutorials.
Apart from the problem with how you have arranged your threads, you have a incorrect use of wait()/notify()
notify() is stateless. If no thread is waiting, nothing will be notified. If you wait() later it will not be notified.
wait() can wake spuriously. Just because wait() woke doesn't mean anything notified it.
This means you need to associate wait/notify with state (in fact it's rather pointless without it)
For example.
// to notify
synchronized(lock) {
signalled = true;
lock.notify();
}
// to wait
synchronized(lock) {
while(!signalled)
lock.wait();
}

Code in synchronized block

Is there any difference of placing timlesProc(100); inside or outside synchronized block like shown commented line in ThreadA.
According to my understanding there is no difference, because both threads are in running mode and both can be executed in the same time. But according experiments, when timlesProc(100); is inside synchronized - it always runs first, then b.sync.wait(); and no 'wait forever' problem. When timlesProc(100); outside synchronized - I always get 'waiting forever'. Why it is so, or my understanding is not correct?
class ThreadA {
public static void timlesProc(int count)
{
for(int i=0;i<count;i++)
{
System.out.println(Thread.currentThread().getName()+" "+ Integer.toString(i));
}
}
public static void main(String [] args) {
ThreadB b = new ThreadB();
b.start();
//timlesProc(100);
synchronized(b.sync)
{
timlesProc(100);
try
{
System.out.println("Waiting for b to complete...");
b.sync.wait();
System.out.println("waiting done");
} catch (InterruptedException e) {}
}
}
}
class ThreadB extends Thread {
Integer sync = new Integer(1);
public void run() {
synchronized(sync)
{
sync.notify();
System.out.println("notify done");
}
}
}
You have a race condition. If the timlesProc method is outside the synchronized, it's very probable that you will have a context switch and the other Thread will be able to execute acquiring the lock and notifying the main Thread (even if it wasn't waiting). Then when you get to
b.sync.wait();
you wait forever because there is nothing left to notify() it.
If you put the timlesProc inside the synchronized, you reach the wait() and then get notified. The program then finishes.
See Cruncher's answer for another possibility of your program waiting forever.
Actually, even if the timlesProc call is inside the synchronized block, there is still a race condition, just less likely to happen.
If b.start() happens, and it aquires the sync lock before the main thread, then it will still notify first causing the same problem that Sotirios Delimanolis mentions in his answer.

Categories

Resources