如何在Java中同步工作
首先,这是一个示例:
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();
}
}
我没有得到的是如何发生堵塞。 主函数启动两个线程,每个线程开始自己的弓。
“同步”块究竟是什么? 运行同一个对象的相同功能(正如我原先所想的那样)? 同一个类的所有对象都具有相同的功能? 同一个对象的所有同步函数? 所有同一类的所有对象的同步函数?
在这里帮助我。
在Java中,每个Object
提供了一个线程synchronize
或锁定的能力。 当方法同步时,该方法使用其对象实例作为锁。 在你的例子中,方法bow
和bowBack
是synchronized
,并且都在同一个班级Friend
。 这意味着执行这些方法的任何线程都将在Friend
实例上同步它的锁。
导致死锁的一系列事件是:
alphonse.bow(gaston)
,它在alphonse
Friend
对象上synchronized
。 这意味着线程必须从这个对象获取锁。 gaston.bow(alphonse)
,它在gaston
Friend
对象上synchronized
。 这意味着线程必须从这个对象获取锁。 bowback
并等待gaston
上的锁定被释放。 bowback
并等待alphonse
上的锁被释放。 更详细地显示事件的顺序:
main()
开始在主Therad中执行(称之为线程#1),创建两个Friend
实例。 到现在为止还挺好。 new Thread(new Runnable() { ...
Thread#2调用alphonse.bow(gaston)
,它在alphonse
Friend
对象上synchronized
来启动它的第一个新线程(称为线程2)。线程#2因此获得了alphonse
物体的“锁定”并进入了bow
法。 gaston.bow(alphonse)
,它在gaston
Friend
对象上同步。 由于没有人获得gaston
对象实例的“锁定”,因此线程#3成功获取此锁并输入了bow
方法。 bower.bowBack(this);
与bower
是gaston
的例子的gaston
。 这是gaston.bowBack(alphonse)
的调用的逻辑等价物。 因此,该方法在gaston
实例上synchronized
。 此对象的锁已被获取并由另一个线程(线程#3)保存。 因此,线程#2必须等待gaston
上的锁被释放。 线程处于等待状态,允许线程3进一步执行。 bowback
,在这种情况下,它在逻辑上与调用alphonse.bowBack(gaston)
。 要做到这一点,它需要获取alphonse
实例的锁,但这个锁由Thread#2保存。 此线程现在处于等待状态。 而你现在处于一个线程无法执行的位置。 线程#2和线程#3都在等待锁释放。 但是没有一个线程正在进行,这两个锁都不能被释放。 但是如果没有释放锁,这两个线程都不能取得进展。
因此:僵局!
死锁通常取决于发生的特定事件顺序,这可能使得难以调试,因为它们很难重现。
同步有两个作用:
简而言之,它会阻止对同一对象的同步方法的任何调用。
同一对象的所有同步函数。 标记一个“synchronized”方法与在方法的整个内容中放置一个“synchronized(this){”块非常相似。 我不说“相同”的原因是因为我不知道编译器是否发出相同的字节码,但AFAIK定义的运行时效果是相同的。
死锁是一种经典的锁定反转。 一个线程锁定alphonse。 然后(或同时在多核系统上)另一个线程锁定gaston。 这部分要求线程的调度恰好恰好在正确的点交叉。
然后,每个线程(以任何顺序或同时)尝试获取已由另一线程保持的锁,并因此每个线程都进入休眠状态。 直到另一个释放它的锁,它们都不会唤醒,但它们都不会在它醒来(或终止)之前释放它的锁。
链接地址: http://www.djcxy.com/p/16337.html