同步功能在Java中是如何工作的?

2022-09-03 13:08:19

自从我开始用Java编程以来,我一直在想这个问题(大约一两年)。在C语言中,我们必须知道不同的方法才能正确避免线程之间的死锁,因此同步方法之间有更多的选择。

那么Java呢?当我们同步时,它如何避免线程陷入死锁状态?它如何在内部工作?是否因为我们在比C(或C++)更高的级别上进行同步而避免了死锁?任何关于Java中的死锁和同步的文档?


答案 1

在引擎盖下,它使用两个操作码,并在字节码级别获取/释放JVM全局级别的对象引用的锁。我强烈建议您阅读 Java 虚拟机如何执行线程同步monitorentermonitorexit


答案 2

我们在多线程代码中遇到的主要问题是共享数据,我同意并发化过程的目的,并且“正式”发生,在视差化处理期间,线程需要访问以读/写共享数据。

java synchroniz 关键字允许执行以下操作:

它告诉 JVM 在对象的监视器或同步代码段上放置一个锁,这使其能够独占访问该部分代码或对象。

下面是单例的一个示例:

public class Singleton {
    private Singleton INSTANCE;

    private Singleton() {
    }

    public Singleton getInstance() {
        if (null == INSTANCE) {
            INSTANCE = new Singleton();
        }
        return INSTANCE;
    }
}

这个单例不是线程安全的,如果一个线程试图获取一个实例,而另一个线程也在尝试做同样的事情(争用条件),则可能发生这样的情况:在线程号一完成实例创建之前,第二个线程已经可以访问该方法并创建自己的单例实例,这意味着在T时间我们应该有两个单例实例(称为当时的多顿)。getInstance()

为了解决这个问题,我们必须同步单例的创建行为,这可以通过本身的if语句上方的关键字来完成:synchronizedINSTANCE

public class Singleton {
    private Singleton INSTANCE;

    private Singleton() {
    }

    public Singleton getInstance() {
        synchronized (Singleton.class) {
            if (null == INSTANCE) {
                synchronized(Singleton.class) {
                   Singleton inst = new Singleton();
                   INSTANCE = inst;   
                }
            }
        }
        return INSTANCE;
    }
}

结果是,当第一个线程询问 Singleton 实例时,在创建期间,JVM 将在 INSTANCE 的监视器上放置一个锁,拒绝对 INSTANCE 的任何访问,直到线程 1 完成其请求。

也有不同的方法可以实现这一目标,之前引用的书是学习的极好来源,javadoc也是如此。


推荐