【发布时间】:2019-03-02 20:08:30
【问题描述】:
按照下面的代码,我有两个 A 类实例 - a1 和 a2。并分别在两个实例上调用方法 foo()。
foo() 方法中有一个同步块,它被锁定在调用对象上。由于它是实例级锁定,因此这两个方法应该同时开始执行,因为它们是从两个单独的实例中调用的。但是,它们是按顺序执行的。
是不是因为两个实例都是从同一个主线程调用的?
代码更改:使 A 类实现 Runnable,将 foo() 重命名为 run(),从 main 分叉一个线程 t,从主线程调用 a1.run(),从线程 t 调用 a2.run()。尽管从两个线程(主线程和线程 t)调用了两个 A 实例 - a1 和 a2,但同步块(this)似乎被锁定了。
我的理解是“this”指的是不同的调用 Runnable 实例,甚至线程也不同。所以,Thread.sleep 不应该让其他线程阻塞。那么,为什么两个 run 调用没有并行发生呢?
预期输出(应该并行执行)
main <time> Inside A.run
Thread-0 <time> Inside A.run
Thread-0 <time+4s> Exiting A.run
main <time+5s> Exiting A.run
实际输出(顺序执行)
main <time> Inside A.run
main <time+5s> Exiting A.run
Thread-0 <time+5s> Inside A.run
Thread-0 <time+9s> Exiting A.run
import java.time.*;
import java.time.format.DateTimeFormatter;
public class Test {
public static void main(String[] args) {
/*A a1 = new A(5000); A a2 = new A(4000);
a1.foo(); a2.foo();*/
A a1 = new A(5000); A a2 = new A(4000);
Thread t = new Thread(a2);
/*a1.run(); t.start();*/
t.start(); a1.run(); // <-- putting t.start() before a1.run() solves the issue
}
}
class A implements Runnable {
public long waitTime;
public A() {}
public A(long timeInMs) {
waitTime = timeInMs;
}
public void run() {
synchronized(this) {
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
LocalDateTime time = LocalDateTime.now();
System.out.println(Thread.currentThread().getName() + " " + formatter.format(time) + " Inside A.run");
Thread.sleep(waitTime);
time = LocalDateTime.now();
System.out.println(Thread.currentThread().getName() + " " + formatter.format(time) + " Exiting A.run");
} catch (InterruptedException e) {}
}
}
}
【问题讨论】:
标签: multithreading synchronization thread-safety synchronized thread-synchronization