我创建了一个简单的工人:
public class Worker {
public synchronized void writeData() {
try {
System.out.println("write Data , thread id = " + Thread.currentThread().getId());
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void readData() {
try {
System.out.println("readData , thread id = " + Thread.currentThread().getId());
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
AFAIK,如果多个线程访问相同的Worker
实例,则synchronized
仅阻止访问相同方法的线程。 AKA如果线程A调用writeData而B使用readData,它们不会相互影响(如果我错了,请纠正我)。
但是,当我尝试通过以下代码演示它时:
private static void testWithThreads() {
final Worker worker = new Worker();
new Thread(() -> {
System.out.println("start read thread");
for (int i = 0; i < 20; i++) {
worker.readData();
}
}).start();
new Thread(() -> {
System.out.println("start write thread");
for (int i = 0; i < 20; i++) {
worker.writeData();
}
}).start();
}
我得到了这样的输出(注意我们这里有Thread.sleep
2秒钟):
start read thread
readData , thread id = 10
start write thread
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
write Data , thread id = 11
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
readData , thread id = 10
任何人都可以向我解释这个吗?它们似乎以某种方式相互阻挡。
答案 0 :(得分:0)
synchronized
同步对方法所属的Object的所有同步方法的访问,只有一个线程可以在该对象的任何同步方法中执行。其他线程即使尝试访问除第一个线程之外的其他synchronized
方法也会等待。
其他线程将阻塞,直到第一个线程从同步块中退出。
在for
循环中调用同步方法之间的代码中,有一个很小的时隙,其他线程可以在第一次再次进入readData()之前进入writeData() - 一个典型的{{ 1}}循环不是原子操作 - 但是这个时间段很小,很少发生 - 因此你的输出看起来像是以某种方式相互阻挡 - 并且在一点上风改变而其他线程起带头作用。
更具体地说,注释指向每个for循环中“非同步”时隙开始的位置:
for
如果你想要更好的交错,你可以做以下事情之一:
答案 1 :(得分:0)
synchronized仅阻止访问相同方法的线程
错误。它阻止尝试在同一对象上同步的线程。
答案 2 :(得分:0)
它的工作原理是如果A对Worker实例使用writeData,那么在有机会之前,B不能使用同一Worker的readData或writeData。
如果您希望输出为:
读
写
读
写
等...
然后我会建议使用函数wait();和notifyAll(); 通过这种方式,您可以使线程A在完成后给线程B一个转弯,反之亦然。
您可以阅读有关wait()和notifyAll()的更多信息 here