If I Synchronized Two Methods on the Same Class, Can They Run Simultaneously

Do two synchronized methods execute simultaneously

If t1 access the m1 method (synchronized method), could t2 thread access m2 method (synchronized method) simultaneously?

The synchronized keyword applies on object level, and only one thread can hold the lock of the object. So as long as you're talking about the same object, then no, t2 will wait for t1 to release the lock acquired when it entered m1.

The thread can however release the lock without returning from the method, by calling Object.wait().

If not, what would be the state of t2 ?

It would sit tight and wait for t1 to release the lock (return from the method or invoke Object.wait()). Specifically, it will be in a BLOCKED state.

Thread state for a thread blocked waiting for a monitor lock. A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or reenter a synchronized block/method after calling Object.wait.

Sample code:

public class Test {

public synchronized void m1() {
try { Thread.sleep(2000); }
catch (InterruptedException ie) {}
}

public synchronized void m2() {
try { Thread.sleep(2000); }
catch (InterruptedException ie) {}
}

public static void main(String[] args) throws InterruptedException {
final Test t = new Test();
Thread t1 = new Thread() { public void run() { t.m1(); } };
Thread t2 = new Thread() { public void run() { t.m2(); } };

t1.start();
Thread.sleep(500);

t2.start();
Thread.sleep(500);

System.out.println(t2.getState());
}
}

Output:

BLOCKED

two different synchronized methods of the same object?

No. A synchronized method in Java is identical to the whole method having its body wrapped in a synchronized (this) block. So if one thread is in a synchronized method, another thread cannot simultaneously be in a different synchronized method on the same object.

The way this relates to a Vector is that you don't want some code trying to remove an element while other code is trying to add an element. This is the concept of a critical section; you not only don't want someone else trying to do what you're doing, you also don't want someone else doing something different that would interfere.

Does synchronized work for all methods in a class or only 1?

The JLS, § 17.1 is quite verbose about this:

A synchronized method (§8.4.3.6) automatically performs a lock action when it is invoked; its body is not executed until the lock action has successfully completed. If the method is an instance method, it locks the monitor associated with the instance for which it was invoked (that is, the object that will be known as this during execution of the body of the method). If the method is static, it locks the monitor associated with the Class object that represents the class in which the method is defined. If execution of the method's body is ever completed, either normally or abruptly, an unlock action is automatically performed on that same monitor.

Oracle's official tutorial on synchronized Methods phrases it a little bit more understandable:

...

  • First, it is not possible for two invocations of synchronized methods on the same object to interleave. ...

...

In this synchronization is not working. Why? I have synchronized all methods. Can anyone please tell and provide solution for the same?

A synchronized method will prevent other threads to enter into a synchronized block on the same object the method is synchronized on. Each thread has two methods in your example, so for instance while first is running, second cannot run, but there is nothing to prevent third from running.

You need to synchronize all methods on the same object:

Object s=new Object();
A a1=new A(s);
B b1=new B(s);
C c1=new C(s);
class A implements Runnable{
Object s;
public A(s Object) {
this.s=s;
}
public void first(){
synchronized(s) {
for(int i=0;i<=10;i++){
System.out.println("Table of 13 is "+13*i);
}
}
}

Synchronized methods of different objects of the same class

Depends. If the methods are static, then they synchronize on the class-object and interleaving is impossible. If they are non-static, then they synchronize on the this-object and interleaving is possible. The following example should clarify the behaviour.

import java.util.ArrayList;
import java.util.List;

class Main {
public static void main(String... args) {
List<Thread> threads = new ArrayList<Thread>();

System.out.println("----- First Test, static method -----");
for (int i = 0; i < 4; ++i) {
threads.add(new Thread(() -> {
Main.m1();
}));
}
for (Thread t : threads) {
t.start();
}
for (Thread t : threads) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

System.out.println("----- Second Test, non-static method -----");
threads.clear();
for (int i = 0; i < 4; ++i) {
threads.add(new Thread(() -> {
new Main().m2();
}));
}
for (Thread t : threads) {
t.start();
}
for (Thread t : threads) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

System.out.println("----- Third Test, non-static method, same object -----");
threads.clear();
final Main m = new Main();
for (int i = 0; i < 4; ++i) {
threads.add(new Thread(() -> {
m.m2();
}));
}
for (Thread t : threads) {
t.start();
}
for (Thread t : threads) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public static synchronized void m1() {
System.out.println(Thread.currentThread() + ": starting.");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + ": stopping.");
}

public synchronized void m2() {
System.out.println(Thread.currentThread() + ": starting.");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + ": stopping.");
}
}

For more details, see this oracle page.



Related Topics



Leave a reply



Submit