问题描述
首先,这是一个示例:>
public class Deadlock {
static class Friend {
private final String name;
public Friend(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public synchronized void bow(Friend bower) {
System.out.format("%s: %s has bowed to me!%n",
this.name, bower.getName());
bower.bowBack(this);
}
public synchronized void bowBack(Friend bower) {
System.out.format("%s: %s has bowed back to me!%n",
this.name, bower.getName());
}
}
public static void main(String[] args) {
final Friend alphonse = new Friend("Alphonse");
final Friend gaston = new Friend("Gaston");
new Thread(new Runnable() {
public void run() { alphonse.bow(gaston); }
}).start();
new Thread(new Runnable() {
public void run() { gaston.bow(alphonse); }
}).start();
}
}
我不明白的是阻塞是如何发生的..main 函数启动了两个线程,每个线程都开始自己的鞠躬.
What I don't get is how the blockage occurs. The main function initiates two threads that each begin their own bows.
同步"块究竟是什么?为同一个对象运行相同的函数(正如我最初认为的那样)?同一类的所有对象的相同功能?同一个对象的所有同步函数?同一个类的所有对象的所有同步函数?
What exactly does 'synchronized' block? The same function running for the same object (as I originally thought)? The same function for all objects of the same class? All synchronized functions for the same object? All synchronized functions for all objects of the same class?
帮帮我.
推荐答案
在 Java 中,每个 Object
都为线程提供了在其上同步
或锁定的能力.当一个方法被同步时,该方法使用它的对象实例作为锁.在您的示例中,方法 bow
和 bowBack
都是 synchronized
,并且都在同一类 Friend
中.这意味着任何执行这些方法的线程都会在 Friend
实例上同步作为它的锁.
In Java, each Object
provides the ability for a Thread to synchronize
, or lock, on it. When a method is synchronized, the method uses its object instance as the lock. In your example, the methods bow
and bowBack
are both synchronized
, and both are in the same class Friend
. This means that any Thread executing these methods will synchronize on a Friend
instance as its lock.
导致死锁的一系列事件是:
A sequence of events which will cause a deadlock is:
- 第一个线程开始调用
alphonse.bow(gaston)
,这是synchronized
在alphonse
Friend
目的.这意味着线程必须从该对象获取锁. - 第二个线程开始调用
gaston.bow(alphonse)
,它在gaston
Friend
上同步
目的.这意味着线程必须从该对象获取锁. - 现在开始的第一个线程调用
bowback
并等待gaston
上的锁被释放. - 现在启动的第二个线程调用
bowback
并等待alphonse
上的锁被释放.
- The first Thread started calls
alphonse.bow(gaston)
, which issynchronized
on thealphonse
Friend
object. This means the Thread must acquire the lock from this object. - The second Thread started calls
gaston.bow(alphonse)
, which issynchronized
on thegaston
Friend
object. This means the Thread must acquire the lock from this object. - The first thread started now calls
bowback
and waits for the lock ongaston
to be released. - The second thread started now calls
bowback
and waits for the lock onalphonse
to be released.
要更详细地显示事件的顺序:
To show the sequence of events in much more detail:
main()
开始在主 Therad(称为线程 #1)中执行,创建两个Friend
实例.到目前为止,一切都很好.- 主线程使用代码
new Thread(new Runnable() { ...
开始它的第一个新线程(称之为线程 #2).线程 #2 调用alphonse.bow(gaston)
,它是alphonse
Friend
对象上的synchronized
.因此,线程 #2 获得了alphonse
对象的锁"code>alphonse 对象并进入bow
方法. - 此处出现一个时间片,原始线程有机会进行更多处理.
- 主线程启动第二个新线程(称为线程 #3),就像第一个线程一样.线程 #3 调用
gaston.bow(alphonse)
,它在gaston
Friend
对象上同步.由于还没有人获得gaston
对象实例的锁",线程 #3 成功地获得了这个锁并进入了bow
方法. - 此处出现一个时间片,线程 #2 有机会进行更多处理.
- 线程 #2 现在调用
bower.bowBack(this);
,其中bower
是对gaston
实例的引用.这在逻辑上等同于gaston.bowBack(alphonse)
的调用.因此,此方法在gaston
实例上同步
.此对象的锁已被获取并由另一个线程(线程 #3)持有.因此,线程 #2 必须等待gaston
上的锁被释放.线程进入等待状态,允许线程 #3 进一步执行. - 线程 #3 现在调用
bowback
,在本例中它在逻辑上与调用alphonse.bowBack(gaston)
相同.为此,它需要获取alphonse
实例的锁,但该锁由线程 #2 持有.该线程现在处于等待状态.
main()
begins to execute in the main Therad (call it Thread #1), creating twoFriend
instances. So far, so good.- The main Thread starts its first new Thread (call it Thread #2) with the code
new Thread(new Runnable() { ...
. Thread #2 callsalphonse.bow(gaston)
, which issynchronized
on thealphonse
Friend
object. Thread #2 thus acquires the "lock" for thealphonse
object and enters thebow
method. - A time slice occurs here and the original Thread gets a chance to do more processing.
- The main Thread starts a second new Thread (call it Thread #3), just like the first one. Thread #3 calls
gaston.bow(alphonse)
, which is synchronized on thegaston
Friend
object. Since no-one has yet acquired the "lock" for thegaston
object instance, Thread #3 successfully acquires this lock and enters thebow
method. - A time slice occurs here and Thread #2 gets a chance to do more processing.
- Thread #2 now calls
bower.bowBack(this);
withbower
being a reference to the instance forgaston
. This is the logical equivalent of a call ofgaston.bowBack(alphonse)
. Thus, this method issynchronized
on thegaston
instance. The lock for this object has already been acquired and is held by another Thread (Thread #3). Thus, Thread #2 has to wait for the lock ongaston
to be released. The Thread is put into a waiting state, allowing Thread #3 to execute further. - Thread #3 now calls
bowback
, which in this instance is logically the same as the callalphonse.bowBack(gaston)
. To do this, it needs to acquire the lock for thealphonse
instance, but this lock is held by Thread #2. This Thread is now put into a waiting state.
而您现在处于两个线程都无法执行的位置.线程#2 和线程#3 都在等待释放锁.但是如果没有线程取得进展,这两个锁都不能被释放.但是如果不释放锁,两个线程都无法取得进展.
And you are now in a position where neither Thread can execute. Both Thread #2 and Thread #3 are waiting for a lock to be released. But neither lock can be released without a Thread making progress. But neither thread can make progress without a lock being released.
因此:死锁!
死锁通常取决于发生的特定事件序列,这会使调试变得困难,因为它们很难重现.
Deadlocks very often depend on a specific sequence of events occurring, which can make then difficult to debug since they can be difficult to reproduce.
这篇关于Java 中同步是如何工作的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!