sha*_*ome 2 java multithreading synchronization locks
我知道通过同步静态和非静态方法来分别锁定类和实例的锁定概念。我无法理解的是,类级锁是如何实现的?我的意思是,类只是一个模板,没有物理意义。那么,当我们说通过同步静态方法实现类级锁定时,会发生什么?该类的所有对象是否都被锁定或其他一些进程?
通过我的搜索,我发现有类对象(Class.class)并且在这个类对象上获取了锁。但是,该类的所有实例又是如何被锁定的呢?
该类的所有对象是否都被锁定或其他一些进程?
首先,让我们谈谈“锁定”一个对象是什么意思。
Foobar foobar = new Foobar();
synchronized (foobar) {
...
}
Run Code Online (Sandbox Code Playgroud)
您可能会说当线程在synchronized块中时 foobar 对象被“锁定” 。但这对程序有什么作用呢?许多新手错误地认为它会阻止其他线程访问该对象。但是,事实并非如此。是什么synchronized呢-同步的唯一的事情那样-是要保证不超过一个线程可以对同一对象在同一时间同步。
上例中程序员的意图可能是防止其他线程看到 foobar 处于不一致状态。在这种情况下,访问 foobar 的每个方法和每个代码片段都必须在 foobar 上同步。把 foobar 想象成有很多门的大房间。使用 foobar 的每种方法就像一扇不同的门。如果你想让人们远离房间,只锁一扇门是无济于事的。你必须锁定所有这些。
所以现在,对于你的问题:
当我们说通过同步静态方法实现类级锁定时会发生什么?
简单的。这个:
class Foobar {
static synchonized void do_something() {
...
}
}
Run Code Online (Sandbox Code Playgroud)
与此完全相同:
class Foobar {
static void do_something() {
synchronized(Foobar.class) {
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
你总是在一个对象上同步。好吧,一个类就是一个对象。当一个static方法是 时synchronized,这仅仅意味着方法体在类对象上是同步的。
由于一个类是一个单例对象,这意味着没有两个线程可以同时进入同一个静态同步方法。在我之前的示例中,变量 foobar 可以在不同时间引用不同的对象,但在静态示例中, Foobar.class 保证始终引用相同的单例。
编辑:正如@Danny 指出的那样,在 Foobar 类上同步的块(我的第二个示例)与在 Foobar 类的实例上同步的块(我的第一个示例)之间没有联系。实例和类对象是两个不同的对象,因此没有什么可以阻止一个线程在实例上同步,而另一个线程在类上同步。同样,没有什么可以阻止两个不同的线程在两个不同的实例上同步。新手经常犯的另一个错误是认为一次只有一个线程可以进入这个synchronized块:
Integer n = ...;
synchronized (n) {
n = n+1;
...
}
Run Code Online (Sandbox Code Playgroud)
但事实并非如此。被锁定的不是变量 n,而是 Integer 类的特定实例。每个进入块的线程都会创建一个新的 Integer 实例并将其分配给 n。因此,当下一个线程出现时,n 不再指代第一个线程已同步的同一个实例。
| 归档时间: |
|
| 查看次数: |
3032 次 |
| 最近记录: |