
经过我测试,此方案可行,不会造成死锁。
方案二
在Account中包含一个唯一的,不可变的,值。比如说账号等。通过对这个值对对象进行排序。
具体代码如下
public class InduceLockOrder2 {
public static void transferMoney(final Account fromAcct, final Account toAcct, final int amount)
throws Exception {
class Helper {
public void transfer() throws Exception {
if (fromAcct.compareTo(amount) < 0) {
throw new Exception();
} else {
fromAcct.debit(amount);
toAcct.credit(amount);
}
}
}
int fromHash = fromAcct.getAccNo();
int toHash = toAcct.getAccNo();
if (fromHash < toHash) {
synchronized (fromAcct) {
synchronized (toAcct) {
new Helper().transfer();
}
}
} else if (fromHash > toHash) {
synchronized (toAcct) {
synchronized (fromAcct) {
new Helper().transfer();
}
}
}
}
static class Account {
private int balance = 100000;
private final int accNo;
private static final AtomicInteger sequence = new AtomicInteger();
public Account() {
accNo = sequence.incrementAndGet();
}
void debit(int m) throws InterruptedException {
Thread.sleep(6);
balance = balance + m;
}
void credit(int m) throws InterruptedException {
Thread.sleep(6);
balance = balance - m;
}
int getBalance() {
return balance;
}
int getAccNo() {
return accNo;
}
public int compareTo(int money) {
if (balance > money) {
return 1;
}else if (balance < money) {
return -1;
}else {
return 0;
}
}
}
}
经过测试此方案也可行。
2.2在协作对象之间发生的死锁

根据前面两条规则,我们可以知道,如果多个线程同时调用这个函数,当一个线程取得同步锁之后,其他线程就会阻塞在pthread_mutex_lock函数,而当那个取得锁的线程执行到pthread_cond_wait并阻塞之后,在从这个函数返回(条件满足)之前,会释放掉锁,所以其他线程也能一个一个都执行到pthread_cond_wait这里阻塞。需要特别理解的一点是,与sleep方法不同的是wait方法调用完成后,线程将被暂停,但wait方法将会释放当前持有的监视器锁(monitor),直到有线程调用notify/notifyall方法后方能继续执行,而sleep方法只让线程休眠并不释放锁。调用某个对象的 wait() 方法能让 当前线程阻塞,并且当前线程必须拥有此对象的monitor(即锁)。
场景如下:Taxi代表对象,包含当前位置和目的地。Dispatcher代表车队。当一个线程收到GPS更新事件时掉用setLocation,那么它首先更新的位置,然后判断它是否到达目的地。如果已经到达,它会通知Dispatcher:它需要一个新的目的地。因为setLocation和notifyAvailable都是同步方法,因此掉用setLocation线程首先获取taxi的锁,然后在获取Dispatcher的锁。同样,掉用getImage的线程首先获取Dispatcher的锁,再获取每一个taxi的锁,这两个线程按照不同的顺序来获取锁,因此可能导致死锁。
能造成死锁的代码如下:
//会发生死锁
public class CooperatingDeadLock {
// 坐标类
class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
// 类
class Taxi {
private Point location, destination;
private final Dispatcher dispatcher;
public Taxi(Dispatcher dispatcher) {
this.dispatcher = dispatcher;
}
public synchronized Point getLocation() {
return location;
}
public synchronized void setLocation(Point location) {
this.location = location;
if (location.equals(destination)) {
dispatcher.notifyAvailable(this);
}
}
public synchronized Point getDestination() {
return destination;
}
public synchronized void setDestination(Point destination) {
this.destination = destination;
}
}
class Dispatcher {
private final Set<Taxi> taxis;
private final Set<Taxi> availableTaxis;
public Dispatcher() {
taxis = new HashSet<>();
availableTaxis = new HashSet<>();
}
public synchronized void notifyAvailable(Taxi taxi) {
availableTaxis.add(taxi);
}
public synchronized Image getImage() {
Image image = new Image();
for(Taxi t:taxis) {
image.drawMarker(t.getLocation());
}
return image;
}
}
class Image{
public void drawMarker(Point p) {
}
}
}
解决方案:使用开放掉用。
如果再调用某个方法时不需要持有锁,那么这种调用就被称为开放掉用。这种调用能有效的避免死锁,并且易于分析线程安全。
修改后的代码如下:
//此方案不会造成死锁
public class CooperatingNoDeadlock {
// 坐标类
class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
// 类
class Taxi {
private Point location, destination;
private final Dispatcher dispatcher;
public Taxi(Dispatcher dispatcher) {
this.dispatcher = dispatcher;
}
public synchronized Point getLocation() {
return location;
}
public void setLocation(Point location) {
boolean reachedDestination;
synchronized (this) {
this.location = location;
reachedDestination = location.equals(destination);
}
if (reachedDestination) {
dispatcher.notifyAvailable(this);
}
}
public synchronized Point getDestination() {
return destination;
}
public synchronized void setDestination(Point destination) {
this.destination = destination;
}
}
class Dispatcher {
private final Set<Taxi> taxis;
private final Set<Taxi> availableTaxis;
public Dispatcher() {
taxis = new HashSet<>();
availableTaxis = new HashSet<>();
}
public synchronized void notifyAvailable(Taxi taxi) {
availableTaxis.add(taxi);
}
public Image getImage() {
Set<Taxi> copy;
synchronized (this) {
copy = new HashSet<>(taxis);
}
Image image = new Image();
for(Taxi t:copy) {
image.drawMarker(t.getLocation());
}
return image;
}
}
class Image{
public void drawMarker(Point p) {
}
}
}
总结:活跃性故障是一个非常严重的问题,因为当出现活跃性故障时,除了终止应用程序之外没有其他任何机制可以帮助从这种故障中恢复过来。最常见的活跃性故障就是锁顺序死锁。在设计时应该避免产生顺序死锁:确保线程在获取多个锁时采用一直的顺序。最好的解决方案是在程序中始终使用开放掉用。这将大大减小需要同时持有多个锁的地方,也更容易发现这些地方。
梦貂蝉神兽进阶数据详解是怎么回事呢,想必大家在游戏过程中会遇到梦貂蝉神兽进阶数据详解的问题,今天小编带大家了解一下关于梦貂蝉神兽进阶数据详解的问题,如果对梦貂蝉神兽进阶数据详解有什么疑问的话,大家可以进行留言,小编会针对梦貂蝉神兽进阶数据详解的问题给大家更详细的解答。如果你有任何关于下载方面的疑问,如果你有什么想听的儿歌找不到,如果你有优秀的儿歌要推荐,都可以给我们留言,我们将尽力为你提供最大的帮助,感谢支持妈妈帮“精选儿歌大全”。欢迎各位来参观指导工作,如果您对我们的产品感兴趣或者有任何的疑问,您可以直接给我们留言或直接与我们联络,我们将在收到您的信息后死锁怎么解决,会第一时间及时与您联络。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-113609-2.html
#吴亦凡#哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥
不会因为一次战役而产生巨大偏移
人渣一个说