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
How to Encode Uri Parameter Values
Firestore Query Documents Startswith a String
Why Does Autoreconnect=True Not Seem to Work
Dealing with Randomly Generated and Inconsistent JSON Field/Key Names Using Gson
Can Spring Security Use @Preauthorize on Spring Controllers Methods
Why Isn't a Qualified Static Final Variable Allowed in a Static Initialization Block
Is This a Bug in Files.Lines(), or am I Misunderstanding Something About Parallel Streams
How to Include SQLite Database in Executable Jar
How to Shuffle Characters in a String Without Using Collections.Shuffle(...)
How to Pass a Variable from One Thread Group to Another in Jmeter
Programmatically Shut Down Spring Boot Application
@Transactional Method Called from Another Method Doesn't Obtain a Transaction
Is There an Effective Tool to Convert C# Code to Java Code
Why Are the Level.Fine Logging Messages Not Showing