Class Lock And Object Lock In Multithreading - java

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.

Related

Thread 1 is executing in java synchronized method 1, can Thread 2 then execute in java synchronised method 2?

Was wondering if someone could help clear this up for me. (Student)
Say we have two threads, "Thread1" & "Thread2". If Thread1 is executing in method 1 can Thread2 then execute in method2?
void method1() {
synchronized (this) {
}
}
void method2() {
synchronized (this) {
}
}
I'm either thinking yes, Thread2 can enter as "this" is just the instance of that method or no because "this" is the instance of that class and Thread1 holds onto it.
There isn't a monitor associated with a specific method - there's a monitor associated with an object. So if you're trying to synchronize on the same object in both methods, the second thread will block until the first thread releases the monitor.
(Personally I don't like synchronizing on this anyway - I synchronize on a reference to an object that only my class has access to. But that's a different matter.)
Everybody jumped on an obvious answer here. It is a correct answer, but it is not the only correct answer.
The rule is, two threads can not both synchronize on the same object at the same time. But does this refer to the same object in both method calls? We can't tell because you have not shown us the calls. Consider this example:
class Demo {
synchronized void method1() {
...do something...
}
synchronized void method2() {
...do something else...
}
static void caseA() {
final Demo demo = new Demo();
new Thread(new Runnable(){
#Override
public void run() {
demo.method1();
}
}).start();
new Thread(new Runnable(){
#Override
public void run() {
demo.method2();
}
}).start();
}
static void caseB() {
final Demo demo1 = new Demo();
final Demo demo2 = new Demo();
new Thread(new Runnable(){
#Override
public void run() {
demo1.method1();
}
}).start();
new Thread(new Runnable(){
#Override
public void run() {
demo2.method2();
}
}).start();
}
}
In caseA(), the calls to demo.method1() and demo.method2() can not overlap because both calls synchronize on the same object, but in caseB() the two calls are synchronized on two different instances of the Demo class. In caseB() the method1() call and the method2() call can overlap.
You are using this for synchronization, which is an instance of an object. Synchronization always works on some particular instance of object and only one thread at any given time can acquire lock of (synchronize on) a single instance used for synchronization and.
Both threads can access the methods only if they use separate instances of the object containing those methods.
The second thread will block until the monitor is released by the first as synchronization is done on the same object for both methods.
You'd better synchronized on the static object you want to lock.
Here, your method 2 will be executed by thread 2, but the content of the synchronized block in method 2 will not be executed unless thread 1 has unlock this. Since your synchronization is on a block, and not on a method, the method is not synchronized, but the block is.
If you have a static member on which you want work in the synchronized, use it like:
private static List<Object> myList;
void method1() {
synchronized (myList) {
// do something on myList
}
}
void method2() {
synchronized (myList) {
// do something on myList
}
}
No Thread2 will have to wait until Thread1 is finished executing the code in synchronised block. This is because you are using the same object (this) to lock. If you did something like this:
Object lock1 = new Object();
Object lock2 = new Object();
void method1() {
synchronized (lock1) { }
}
void method2() {
synchronized (lock2) { }
}
Then you would be able to have Thread1 execute method1 and Thread2 execute method2.

How Java manage following scenario?

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.

Why does the non synchronized method get called while acquiring the lock on object?

Iam new to syncronization and multithreading please answer why this code is not getting a lock on object b.
public class Tetsclass {
public static void main(String[] args) {
B b = new B();
A a = new A(b);
A2 a2 = new A2(b);
Thread t1= new Thread(a);
Thread t2= new Thread(a2);
t1.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t2.start();
}
}
class B {
public synchronized void waitfor() {
synchronized (B.class) {
System.out.println("Lock aquired on "+System.currentTimeMillis());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Lock released");
}
}
public void readObject() {
System.out.println("readobject by thread==="+Thread.currentThread().getName()+" on "+System.currentTimeMillis());
}
}
class A2 implements Runnable {
B b=null;
public A2(B b) {
this.b = b;
}
#Override
public void run() {
b.readObject();
}
}
class A implements Runnable {
B b=null;
public A(B b) {
this.b = b;
}
#Override
public void run() {
b.waitfor();
}
}
I expected the output :
Lock aquired on 1380016080337
Lock released
readobject by thread===Thread-1 on 1380016082337
but the output is :
Lock aquired on 1380016080337
readobject by thread===Thread-1 on 1380016082337
Lock released
The readObject method, including its invocation from A2#run, involves no lock acquisition. Therefore the lock your other thread is holding is inconsequential to the progress of the execution of readObject.
Apparently you have a misunderstanding of the semantics of locks. You believe that when you lock B.class, you have locked "the whole class". The state of matters is quite different: B.class is just another object, and all objects have their associated monitor, which can be acquired by a thread. Mutual exclusion happens only between threads which contend to acquire one and the same lock. There is no semantic relationship between an object as a lock and any of its methods, and the same stands for class objects vz. instances of that class.
One way your misunderstanding may have arisen is via the objects used implicitly on synchronized methods: a synchronized instance method acquires its this as a lock, while a synchronized static method acquires a lock on its associated class object.
Its behaving as expected.
Here is what happens on the time line
a - calls wait (which sleeps 5 secs before releasing lock)
a2 - calls read which prints read message.
t t+dt t+dt+5
---------|-----------|--------------------------------|--------------------------|----------
[a starts] [print(lock acquired)] [sleeps(5)] [print(lock released)]
t+2
----------------------------|--------------|--------------------------|--------------
[a2 starts] [print(read message)]
There is no locking of any kind in your readObject()
Since the readObject() doesn't require to acquire a lock, it won't wait for the other thread to release the lock. This confusion might have come because of the Thread.sleep(2000) you've in your test class.
Try to change that to Thread.sleep(10000) and see the output. You'll get your desired result.
In the first case, the A2 thread will wait for 2 secs after A starts, and will execute without any further delay whereas your A is held up for 5 secs when it acquired the lock.
In the second case, the A2 thread will wait for 10 secs after A starts, and within those 10 secs, your A will start, sleep for 5 secs and release the lock, after which your A2 will be executed without any delays.
Class B object can be synchronized to get the output as expected. There is no synchronization is involve in current code execution. To synchronized this code and get the expected output, we can modify Class B as
class B {
public synchronized void waitfor() {
synchronized (B.class) {
System.out.println("Lock aquired on "+System.currentTimeMillis());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Lock released");
}
}
public void readObject() {
synchronized(B.class)
{
System.out.println("readobject by thread==="+Thread.currentThread().getName()+" on "+System.currentTimeMillis());
}
}
}

java synchronized

The Class X have two methods: test and test1.
I've created two threads: t1 and t2. Thread t1 is accessing test method and t2 is accessing test1 method of same object. When t1 is accessing test method which synchronized it acquires lock on object.
Will t2 be able to access test1 method on same object? Why it is able to access this method if t1 has a lock on it?
If I'm executing the following code
X x = new X();
new MyThread(x).start(); // It execute test() method
new MyThread1(x).start();// It execute test1() method
class X
{
String a = "varsha";
public synchronized void test ()
{
try
{
Thread.sleep (6000);
}
catch (InterruptedException e)
{
e.printStackTrace ();
}
}
public void test1 ()
{
synchronized (a)
{
}
}
}
You have two different locks:
test() locks this;
test1() locks this.a.
The two locks are completely independent and thus the two methods can be called at the same time.
Your code is equivalent to the following:
class X
{
String a = "varsha";
public void test ()
{
synchronized (this)
{
try
{
Thread.sleep (6000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
public void test1 ()
{
synchronized(a)
{
}
}
}
So these methods are synchronizing at different objects (this versus a) and thus can be executed concurrently without locking each other.
Note, that I replaced Thread.currentThread ().sleep (6000) with Thread.sleep (6000) because method sleep is static and thus you don't need any instance of Thread in order to use it.
class X {
String a = "varsha";
public synchronized void test(){
try {
//if you are modifying the instance variable here
// then the test1() synchronized block will
//not be given lock permission to t2 thread
// synchronization is for thread safety.
// In your example you are not modifying the instance variable.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void test1(){
synchronized(a){
}
}
}
Here is whats actually happening.
Every object in Java has a "monitor lock", In this case object "x".
There are two threads (MyThread and MyThread1) trying to acquire this lock in the following sequence -
Imagine there is a queue – MyThread is in front of MyThread1 in this queue because you have started MyThread first followed by MyThread1.
MyThread acquires the lock first and it starts executing, you have invoked the sleep() method on it. This will change the state of MyThread from "execution state" to "waiting state" and then to "ready state", it will release the lock at this moment since it is not in execution state. At this point MyThread1 is ahead in the queue and it acquires the lock and starts executing.
This is in a way similar to the concept of "Context Switch". Refer book - Operating System Internals and Design.
When you mark a method as synchronized, it locks the object for that method; meaning no other thread can access that PARTICULAR method for that object. In your case no other thread can access the test method; but of course test1 method can be accessed.

If a synchronized method calls another non-synchronized method, is there a lock on the non-synchronized method

In Java, if a synchronized method contains a call to a non-synchronized, can another method still access the non-synchronized method at the same time? Basically what I'm asking is everything in the synchronized method have a lock on it (including calls to other synchronized methods)?
If a synchronized method calls another non-synchronized method, is there a lock on the non-synchronized method
The answer depends on the context.
If you are in a synchronized method for an object, then calls by other threads to other methods of the same object instance that are also synchronized are locked. However calls by other threads to non-synchronized methods are not locked – anyone can call them at the same time.
public synchronized void someSynchronizedMethod() {
...
someNonSynchronizedMethod();
...
}
// anyone can call this method even if the someSynchronizedMethod() method has
// been called and the lock has been locked
public void someNonSynchronizedMethod() {
...
}
Also, if you call someSynchronizedMethod() but happen to be within the someNonSynchronizedMethod() method, you still hold the lock. The lock is enabled when you enter a synchronized method (or block) and is disabled when you exit that method. You can call all sorts of other unsynchronized methods and they will still be locked.
But you are asking two different things in your question:
In Java, if a synchronized method contains a call to a non-synchronized, can another method still access the non-synchronized method at the same time?
Yes. Other methods can access non-synchronized methods.
Basically what I'm asking is everything in the synchronized method have a lock on it (including calls to other synchronized methods)?
Uh, yes. Other calls to synchronized methods are locked. But non-synchronized methods are not locked.
Also, remember that if the method is static then the lock is on the Class object in the ClassLoader.
// this locks on the Class object in the ClassLoader
public static synchronized void someStaticMethod() {
If the method is an instance method then the lock is on the instance of the class.
// this locks on the instance object that contains the method
public synchronized void someInstanceMethod() {
There are 2 different locks in those 2 cases.
Lastly, when you are dealing with synchronized instance methods, each instance of the class is what is locked. This means that two threads could be in the same synchronized method at the same time with different instances. But if 2 threads try to operate on synchronized methods on the same instance, one will block until the other one exits the method.
If thread A calls synchronized method M1 which in turn calls unsynchronized method M2, then thread B can still call M2 without blocking.
Synchronized method acquires and releases intrinsic lock on the object on which it is called. This is why it may block. Unsynchronized method doesn't attempt to acquire any lock (unless it is done explicitly in the code).
Thus, if you need to ensure mutual exclusion for M2 as well, you should make it synchronized regardless of whether its callers (like M1) are synchronized or not.
The lock doesn't belong to the thread. The lock actually belongs to the object(or Class in case of Class level lock), and a thread acquires lock on the Object(or Class in case of Class level lock) within a synchronized context.
Now, there is no lock propagation in java as it is discussed above. Here is a small demo:
public class TestThread {
/**
* #param args
* #throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
ThreadCreator1 threadCreator1 = new ThreadCreator1();
ThreadCreator2 threadCreator2 = new ThreadCreator2();
Thread t1 = new Thread(threadCreator1,"Thread 1");
Thread t3 = new Thread(threadCreator1,"Thread 3");
Thread t2 = new Thread(threadCreator2,"Thread 2");
t1.start();
Thread.sleep(2000);
t3.start();
}
}
public class ThreadCreator1 implements Runnable {
private static final Task task= new Task();
private static final Task2 task2= new Task2();
#Override
public void run() {
try {
if(Thread.currentThread().getName().equals("Thread 1"))
task.startTask2(task2);
if(Thread.currentThread().getName().equals("Thread 3"))
task2.startTask();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Auto-generated method stub
/**/
}
}
public class Task {
public static final Task task = new Task();
public static List<String> dataList = new ArrayList<String>();
ReentrantLock lock = new ReentrantLock();
public void startTask2(Task2 task2) throws InterruptedException
{
try{
lock.lock();
//new Task2().startTask();
task2.startTask();
}
catch(Exception e)
{
}
finally{
lock.unlock();
}
}
}
public class Task2 {
ReentrantLock lock = new ReentrantLock();
public void startTask() throws InterruptedException
{
try{
//lock.lock();
for(int i =0 ;i< 10;i++)
{
System.out.println(" *** Printing i:"+i+" for:"+Thread.currentThread().getName());
Thread.sleep(1000);
}
}
catch(Exception e)
{
}
/*finally
{
lock.unlock();
}*/
}
}
Just I have used Reentrant lock here.
If the above code is run, then there will be interleaving between thread 1 and thread 3, but if the lock portion of Task2 class is uncommented, then there will be no interleaving and the thread which acquire the lock first will complete fully first, then it will release the lock and then the other thread can carry on.
The lock belongs to the thread, not to the method (or more precisely, its stack frame). It just so happens that if you have a synchronized method, you're guaranteed that the thread will own the lock before the body of the method start, and will release it afterwards.
Another thread can still invoke the second, non-synchronized method. An unsynchronized method can be called by any thread at any time.

Categories