Java:同步块可以交错吗? [英] java: can synchronized block interleave?

查看:44
本文介绍了Java:同步块可以交错吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码的输出(至少对我来说)是意外的

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

  1. 它获取 this 的锁(输入同步块)
  2. 打印等待条件"
  3. 永远陷入无限循环
  4. 另一个线程等待 this 锁进入自己的同步块
  1. it acquires the lock for this (entering the synchronized block)
  2. prints "waiting for condition"
  3. get stuck in the infinite loop forever
  4. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆