1

我研究 Java 的内部结构已经有一段时间了。我很想学习和理解 Java 中线程/锁定是如何发生的。

因此,为了访问同步方法或同步块,线程必须首先获取对象上的锁。所以,现在,这就是我需要更多光的地方。

那么,每当线程获取对象上的锁时,它是否会在内部增加信号量的值?如果答案是肯定的,那么让我们来看看这个场景。

class ABC{ 

    public void method_1(){
        synchronized(xyz){
            ....
        }
    }

    public void method_2(){
        ...
        synchronized(xyz){
            ....
        }
    }
}

因此,假设有两个线程:Thread 1 和 Thread 2。假设Thread1首先进入 method_1,因此首先获得了 xyz 上的锁。而且,现在说,Thread2进入 method_2 并尝试获取 xyz 上的锁定。会发生什么?(对我来说,Thread2 将被阻塞,因为它发现对象的信号量值>0)

让我知道我的推理是否正确。

4

3 回答 3

1

每当线程获取对象上的锁时,它是否会在内部增加信号量的值?

具体实现,但不太可能,由于每个锁只能获得一次,因此不需要计数器。一个简单的切换就可以了。我假设每个锁都持有对拥有它的线程的引用(或 null)。

更新:实际上,它比这要复杂得多。锁还需要维护一个正在等待它的线程列表。此外,线程可以通过等待/通知机制临时释放锁(所以毕竟会有一个入口计数器)。最重要的是,锁管理对性能有很大的影响,因此会进行各种优化。我发现一个从事 JVM 锁定工作的人写的这个有趣的博客。

因此,假设有两个线程:Thread 1 和 Thread 2。假设 Thread1 首先进入 method_1,因此首先获得了 xyz 上的锁。而且,现在说,Thread2 进入 method_2 并尝试获取 xyz 上的锁定。会发生什么?

是的,线程 2 将被阻塞,并等待它最终获得锁。

于 2010-02-21T06:21:55.477 回答
1

你的推理大致正确。线程 2 将被阻塞,并且将保持阻塞直到(至少)线程 1 释放互斥体。

然而,锁通常不是使用带有简单计数器的传统信号量来实现的。通常,只有在对象被重入锁定(例如,如果 Thread1xyz在它已经持有该对象的锁时尝试锁定)或存在对锁的争用时(例如当 Thread2 尝试锁定xyz而 Thread1 将其锁定时)。

但是您不需要关心 Java 锁的实现细节……除非您自己实现 JVM!

于 2010-02-21T06:25:38.283 回答
1

其他答案几乎回答了您的问题,但为了进一步阅读,我建议: Java Concurrency In Practice

于 2010-02-21T10:11:58.383 回答