Here is a code i am having problem with --
public class WaitTest {
public static void main(String[] args) {
Runner rr = new Runner();
Thread t1 = new Thread(rr,"T1");
Thread t2 = new Thread(rr,"T2");
t1.start();
t2.start();
}
}
class Runner implements Runnable{
int i=0;
public void run(){
try{
if(Thread.currentThread().getName().equals("T1")){
bMethod();
aMethod();
}
else{
aMethod();
bMethod();
}
}catch(Exception e){}
}
public synchronized void aMethod() throws Exception{
System.out.println("i="+i+",Now going to Wait in aMethod "+Thread.currentThread().getName());
Thread.currentThread().wait();
System.out.println("Exiting aMethod "+Thread.currentThread().getName());
}
public synchronized void bMethod() throws Exception{
System.out.println("i="+i+",Now going to Wait bMethod "+Thread.currentThread().getName());
i=5;
notifyAll();
System.out.println("Exiting bMethod "+Thread.currentThread().getName());
}
}
The output is :
i=0,Now going to Wait bMethod T1
Exiting bMethod T1
i=5,Now going to Wait in aMethod T1
i=5,Now going to Wait in aMethod T2
My question is :
Why T2 enters in aMethod while T1 is waiting inside? and Why T2 prints
i=5 in aMethod.
When you execute wait, your thread releases the lock and enters the wait state. At this time the other thread is allowed to enter the method. You are using a single instance of Runnable so when one thread sets it to 5, that's what the other thread reads.
1. wait will immediately release the lock, and handover the lock to the other thread.
2. notify will release the lock only when the closing parenthesis of the synchronized block
is reached.
3. As there is only one instance of Runnable here, its after the i = 5, and when the synchronized block ends..then the lock is released.
This code is not doing the wait-notify pattern. The Thread.currentThread().wait() call throws an IllegalMonitorStateException, which is caught and ignored by the run method. Both T1 and T2 throws this exception, and hence you do not see the line Exiting aMethod printed.
The notify call in bMethod is wasted, because no thread ever waits on the intrinsic lock of the rr Runnable.
Related
I tried an interview question with static functions and non static functions as synchronized and one function was non synchronized. As in below code:
public class Resource {
public static synchronized void m1() throws InterruptedException {
System.out.println("Entering m1 method");
Thread.sleep(10000);
System.out.println("Leaving m1 method");
System.out.println();
}
public synchronized void m2() throws InterruptedException {
System.out.println("Entering m2 method");
Thread.sleep(2000);
System.out.println("Leaving m2 method");
System.out.println();
}
public void m3() throws InterruptedException {
System.out.println("Entering m3 method");
Thread.sleep(2000);
System.out.println("Leaving m3 method");
System.out.println();
}
public synchronized void m4() throws InterruptedException {
System.out.println("Entering m4 method");
Thread.sleep(2000);
System.out.println("Leaving m4 method");
System.out.println();
}
}
public class ThreadDemo {
public static void main(String[] args) {
final Resource resource = new Resource();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
resource.m1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
resource.m2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t3 = new Thread(new Runnable() {
#Override
public void run() {
try {
resource.m3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t4 = new Thread(new Runnable() {
#Override
public void run() {
try {
resource.m4();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t3.start();
t4.start();
}
}
Here four threads are created.
T1 is calling static synchronized(m1)
T2, T4 are calling synchronized(m2, m4) and
T3 is calling non synnchronized(m3).
It's output is:
Entering m1 method
Entering m3 method
Entering m2 method
Leaving m3 method
Leaving m2 method
Entering m4 method
Leaving m4 method
Leaving m1 method
My question is:
1) static synchronized method make class level lock. Here what is the meaning of class level locking? If one thread has taken lock and class level lock is occupied then why thread T2 and T3 starts execution?
2) T4 is waiting to complete T2. Although synchronization is applied on two different methods, then why T4 has to wait? If object level lock is working in T2, T4 then in above point why class level locking is not working?
Static method synchronization is an equivalent for
public static void m1() {
synchronize (Resource.class) {
...
}
}
Non-static method synchronization is an equivalent for
public void m2() {
synchronize (this) {
...
}
}
Now if you will have a look where this is using as monitor and where Resource.class object is using as monitor everything should become clear.
A synchronized block in Java is synchronized on some object. All synchronized blocks synchronized on the same object can only have one thread executing inside them at the same time. All other threads attempting to enter the synchronized block are blocked until the thread inside the synchronized block exits the block.
In your case there are two objects. So, this rule is applicable for each object, but not to both.
Regarding your queries:
1) static synchronized method make class level lock. Here what is the meaning of class level locking? If one thread has taken lock and class level lock is occupied then why thread T2 and T3 starts execution?
in case of static synchronized methods, only one thread acquire lock on these methods among multiple instances of class. If you have two different instances : resource1 and resource2 for Resource class, only one thread will succeed in getting lock on m1().
if resource1.m1() method execution is in progress by one thread, other thread can't execute resource2.m1() unless first thread finish the execution of m1().
Since method m3() is non-synchronized method, any thread can invoke this method without wait and getting lock.
Since both m2() and m4() are synchronized, only one thread will succeed in getting lock on same object ( resource in your example). Other thread has to wait until first thread completes the execution of synchrnozied method and release object level lock.
2) T4 is waiting to complete T2. Although synchronization is applied on two different methods, then why T4 has to wait?If object level lock is working in T2, T4 then in above point why class level locking is not working?
synchronized methods:
Making these methods synchronized has two effects:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
static synchronized methods:
The thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.
just see the code
static class ThreadA extends Thread {
public ThreadA(String name) {
super(name);
}
#Override
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + " call notify()");
}
}
}
public static void main(String[] args) throws InterruptedException {
ThreadA t1 = new ThreadA("t1");
synchronized (t1) {
System.out.println("start: " + Thread.currentThread().getName());
t1.start();
t1.wait();
System.out.println(" -- end -- ");
}
}
and the output is:
start: main
t1 call notify()
-- end --
why invoke wait() does not block the main thread
The answer to your question can be found in the javadoc of the join(long millis) method :
This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
(emphasis mine)
So : your main loop stops waiting, as the thread it's waiting on calls notifyAll on itself as it finishes.
As others have pointed out already, the proper way to wait for a thread to finish is to call join.
What you need is Thread.join(). The purpose of Object.wait() is to wait until the monitor lock on that object to be released by another Thread (using Object.notify() or Object.notifyAll()).
public static void main(String[] args) throws InterruptedException {
ThreadA t1 = new ThreadA("t1");
synchronized (t1) {
System.out.println("start: " + Thread.currentThread().getName());
t1.start();
t1.join();
System.out.println(" -- end -- ");
}
}
I was asked to created a dead lock situation. Below code is never creating me dead lock although there is a chance of getting dead lock.
The reason is as follows.
If method1() and method2() both will be called by two or many threads , there is a good chance of deadlock because if thead 1 aquires lock on Sting object while executing method1() and thread 2 acquires lock on Integer object while executing method2() both will be waiting for each other to release lock on Integer and String to proceed further which will never happen.
I wanted to create a dead lock situation but is not creating it.
class Task implements Runnable {
public void method1() {
synchronized (String.class) {
System.out.println("Aquired lock on String.class object");
synchronized (Integer.class) {
System.out.println("Aquired lock on Integer.class object");
}
}
}
public void method2() {
synchronized (Integer.class) {
System.out.println("Aquired lock on Integer.class object");
synchronized (String.class) {
System.out.println("Aquired lock on String.class object");
}
}
}
#Override
public void run() {
method1();
method2();
}
}
public class DeadLock {
public static void main(String args[]) {
Runnable r= new Task();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();
t2.start();
}
}
If you want to increase the chance for deadlock, you can sleep the thread after it acquires the first lock, and before it tries to acquires the second lock. One rough example:
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
public void run() {
synchronized (String.class) {
System.out.println("Thread 1 after acquiring String lock");
Thread.sleep(5000); // Sleep for 5 seconds
synchronized (Integer.class) {
System.out.println("Thread 1 after acquiring Integer lock");
}
}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
synchronized (Integer.class) {
System.out.println("Thread 2 after acquiring Integer lock");
Thread.sleep(5000); // Sleep for 5 seconds
synchronized (String.class) {
System.out.println("Thread 2 after acquiring String lock");
}
}
}
});
t1.start();
t2.start();
}
You will see:
Thread 1 after acquiring String lock
Thread 2 after acquiring Integer lock
or
Thread 2 after acquiring Integer lock
Thread 1 after acquiring String lock
and then deadlock happens.
This is unlikely create a deadlock, as the Task always attempts method1 then method2. You need to have 2 different runnables which call method1 and method2 in opposing orders. Additionally, you probably should consider using a countdown latch that your tasks must wait for at the beginning of run() to provide a higher probability of the 2 threads actually executing concurrently.
I tried some code to justify the reliability of synchronized block locking mechanism. Consider my sample code
My clocking object.
public class MyLock {
final static Object lock=new Object();
}
Class with synchronized blocks
public class Sample {
public void a(String input) {
System.out.println(input+" method a");
synchronized (lock) {
System.out.println("inside synchronized block in a");
try {
System.out.println("waiting in a");
Thread.sleep(5000);
System.out.println("calling b() from a");
new Sample().b("call from a");
System.out.println("waiting again in a");
Thread.sleep(5000);
System.out.println("Running again a");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void b(String input) {
System.out.println(input+" method b");
synchronized (lock) {
System.out.println("bbb " + input);
}
}
}
Test1 class
public class Test1 implements Runnable{
public static void main(String[] args) {
new Thread(new Test1()).start();
new Thread(new Test2()).start();
}
#Override
public void run() {
new Sample().a("call from main");
}
}
Test2 class
public class Test2 implements Runnable {
#Override
public void run() {
new Sample().b("call from main");
}
}
I just did this because I thought there will be a dead lock scenario if same thread witch holding the lock is going to access another method witch locked using same lock. Now consider the out put
call from main method a
call from main method b
inside synchronized block in a
waiting in a
calling b() from a // i thought this will cause a dead lock
call from a method b
bbb call from a
waiting again in a
Running again a
bbb call from main
Now you can see there is no such issue. My question is how Java manage this situation?
synchronized block is Reentrant
By default the lock (mutex to be precise) used in synchronized block is Reentrant, which means if the same thread tries to acquire the same lock again it will not have to wait and will immediately enter the critical block as it already owns that lock.
Where is Reentrancy useful?
Simple answer is Recursion.
Consider the scenario of recursion on a synchronized method,
int synchronized method(int param){
//... some logic
method(param - 1);
}
In this example you would not want the same thread to be blocked for the same lock, as it will never be able to proceed.
Deadlock occurs in this scenario:
Thread A acquires lock A
Thread B acquires lock B
Thread A tries to acquire lock B
Thread B tries to acquire lock A
Now in this situation no one will be able to proceed and hence deadlock. But in your scenario there is only one lock, so the other thread will just wait for the first thread to leave the lock and then continue.
Since your lock object is static it is shared among threads. Once thread A has acquired the lock, and when thread B enters method B of sample class it tries to acquire the same lock Which is owned by thread A. So there is no chance of deadlock.
Problem could have been where thread A tries to acuire the lock it already holds in method B, but this hasnt happened in your case as synchnorized block itself is reenterant but if you would have implemented your own lock class and if you wouldnt have cjecked for renterency, there would have been a dead lock.
I am trying to implementing deadlock condition but somehow I am not able to get it working. Both the threads Thread1 and Thread2 are entering in the run function but only one of them enters in Sub/Sum depending on who entered run first. Example : if Thread2 entered run first the it will call sub() and Thread1 never calls sum(). I have also added sleep time so that Thread2 sleeps before calling sum() and Thread1 gets enough time to enter Sum() but Thread1 never enters.
public class ExploringThreads {
public static void main(String[] args) {
// TODO Auto-generated method stub
threadexample a1 = new threadexample();
Thread t1 = new Thread(a1, "Thread1");
Thread t2 = new Thread(a1,"Thread2");
t1.start();
t2.start();
}
}
class threadexample implements Runnable{
public int a = 10;
public void run(){
if(Thread.currentThread().getName().equals("Thread1"))
sum();
else if(Thread.currentThread().getName().equals("Thread2"))
sub();
}
public synchronized void sum()
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"In Sum");
sub();
}
public synchronized void sub()
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"In Sub");
sum();
}
}
If you really want to create an artificial dead lock, try this:
Thread1 and Thread2 are two threads that want to access the same file.
Thread1 starts, asks for a lock on File1.docx and sleeps for 2 minutes.
Thread2 starts, and makes an exclusive lock on File2.docx and now wants to access File1.docx.
Thread1 wakes up and now wants to access File2.docx which is held by Thread2
Now, this is a circular wait condition
Simple ? =)
This is not how you get a deadlock. Actually this code seems pretty safe :-) Only one thread enters sum/sub at a time because you are using synchronized which synchronizes on "this". There is only one "this" so both threads try to acquire the same lock.
Deadlock occurs, for instance, when Thread1 has one lock, Thread2 has second lock and then Thread1 would like to acquire Thread2's lock while still holding it's lock and Thread2 would like to acquire Thread1's lock while still holding it's lock.
What you could do is:
a) add 2 objects for locking in "threadexample" class (btw classes by convention should start with uppercase):
private final Object sumLock = new Object();
private final Object subLock = new Object();
b) drop the "synchronized" keyword in both sum/sub methods and instead use the synchronized() {} block in each of them. Sum would be synchronized(sumLock) { /* sum's body goes here / } and sub would be synchronized(subLock) { / sub's body goes here */}.
In this case Thread1 would go into sum(), acquire the sumLock and wait. Thread2 would go into sub(), acquire the subLock() and wait. Thread1 would wake up, go into sub() and try to acquire subLock but it's being held by Thread2 so it wait's until Thread2 releases it. In that time Thread2 wakes up, goes into sum() and tries to acquire sumLock which is held by Thread1 so Thread2 waits for Thread1 to release it.
Neither thread will go forward as each one of them is waiting for the other - you have a deadlock.
#Edit: yes you have only 1 instance of "threadexample" and both Thread1 and Thread2 are fighting for the lock but when one of them acquires the lock it will release it after executing sum/sub or sub/sum. For instance let's say Thread1 is first and starts executing sum(). It has the lock. In that case Thread2 will not go into sub() as it is protected by the same lock as Thread1. Thread1 will do sum(), then sub() and then it will release the lock --> Thread2 will go into sub() etc.
This is a working example of 'Deadlock in Action'. Basically what you need to do (and how that usually happens in real world) is that object are locked in opposite order: a first, b second in one thread and b first, a second in another:
package stackoverflow;
public class Deadlock {
final static String a = new String("A");
final static String b = new String("B");
public static void main(String[] args) {
final Thread abLock = new Thread() {
#Override
public void run() {
lock(a, b);
}
};
final Thread baLock = new Thread() {
#Override
public void run() {
lock(b, a);
}
};
abLock.start();
baLock.start();
}
static void lock(String first, String second) {
synchronized (first) {
System.out.println(first);
sleep();
synchronized (second) {
System.out.println(second);
}
}
}
static void sleep() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}