Java:同步块可以交错吗? [英] java: can synchronized block interleave?
问题描述
此代码的输出(至少对我来说)是意外的
I have an unexpected (for me at least) output with this code
public class Test {
static boolean condition = false;
void runme() {
var reader = new Runnable() {
@Override
public void run() {
synchronized (this) {
System.out.println("waiting for condition");
while (!condition) {}
System.out.println("condition is true");
}
}
};
var writer = new Runnable() {
@Override
public void run() {
synchronized (this) {
System.out.println("condition is set to true");
condition = true;
}
}
};
new Thread(reader).start();
new Thread(writer).start();
}
public static void main(String[] args) {
new Test().runme();
}
}
根据文档,如果 reader
对象首先启动,则我预计会出现死锁,因为
Based on the documentation, I expected a deadlock if the reader
object starts first, since
- 它获取
this
的锁(输入同步块) - 打印等待条件"
- 永远陷入无限循环
- 另一个线程等待
this
锁进入自己的同步块
- it acquires the lock for
this
(entering the synchronized block) - prints "waiting for condition"
- get stuck in the infinite loop forever
- the other thread waits for the
this
lock, to get into its own synchronized block
但是,在某些代码运行中,我得到了输出
However, on some runs of the code I get the output
waiting for condition
condition is set to true
condition is true
我丢失了某些东西还是误解了同步块/方法的工作原理?
Am I missing something or have I misunderstood how synchronized blocks/methods work?
推荐答案
在您的代码中, synchronized(this)
指的是两个不同的对象.因此,两个代码都不会阻塞对方,它们只能同时运行.
In your code, synchronized(this)
refers to two different objects. So neither code blocks the other, they just run simultaneously.
查看它的另一种方法是不使用 var
或本地类.只需声明两个与 reader
和 writer
具有相同功能的顶级类即可:
Another way to look at it is to not use var
or local classes. Just declare two top level classes that do the same thing as reader
and writer
:
// var reader = new Runnable() {
class Reader implements Runnable {
@Override
public void run() {
synchronized (this) {
System.out.println("waiting for condition");
while (!condition) {}
System.out.println("condition is true");
}
}
}
// var writer = new Runnable() {
class Writer implements Runnable {
@Override
public void run() {
synchronized (this) {
System.out.println("condition is set to true");
condition = true;
}
}
}
很明显,在这种情况下, this
引用的是每个类的实例,而不是同一对象,因此这两个类永远不会相互阻塞.
It should be pretty obvious that this
in this case refers to an instance of each class, not the same object, so these two classes could never block each other.
这篇关于Java:同步块可以交错吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!