java:同步块(synchronized block)可以交错吗?

标签 java concurrency

我有一个意想不到的(至少对我来说)输出这段代码

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 对象先启动,我预计会出现死锁,因为

  1. 它获取this的锁(进入同步块(synchronized block))
  2. 打印“等待条件”
  3. 永远陷入死循环
  4. 另一个线程等待这个锁,进入它自己的同步块(synchronized block)

但是,在某些代码运行中我得到了输出

waiting for condition
condition is set to true
condition is true

我是否遗漏了什么或者我是否误解了同步块(synchronized block)/方法的工作原理?

最佳答案

两个synchronized (this)语句引用了Runnable匿名类。
所以这两个 Runnable 实例的同步不会对同一个锁进行操作。
您必须在外部类实例上同步以锁定同一监视器,例如:

synchronized (Test.this) {...}

此外,请注意,通过使用 lambda 来实现 Runnable 功能接口(interface),例如:

var writer = () -> {
    synchronized (this) {
        System.out.println("condition is set to true");
        condition = true;
    }
};

您可以保留实际语法(synchronized (this)),因为在这种情况下 this 不引用不存在的匿名类,而是引用外部类实例。

关于java:同步块(synchronized block)可以交错吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50356140/

相关文章:

java - 原子地获取多个锁

java - 我应该从多个线程访问(而不是更改)一个对象吗?

java - Java 是否提供一个 ExecutorService 允许一个 worker 在同一个线程上执行?

java - scala 中 BigInt 与 Byte 数组的内存和性能比较

java - 将数据添加到 JTable 对象的 object[][]

java - 创建空对象

java - 调用方法后出现 NoSuchElement 异常

multithreading - 一个可变借用和多个不可变借用

google-apps-script - 如何为 Google Apps Script Webapp 上的并发用户提供便利?

gps - 测量 gps 距离