Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 死锁的解决方案:锁排序_Multithreading_Operating System_Locking_Mutex_Deadlock - Fatal编程技术网

Multithreading 死锁的解决方案:锁排序

Multithreading 死锁的解决方案:锁排序,multithreading,operating-system,locking,mutex,deadlock,Multithreading,Operating System,Locking,Mutex,Deadlock,在下面的代码中,如果两个线程同时调用transaction()函数,转换不同的帐户,则可能出现死锁 void transaction(Account from, Account to, double amount) { mutex lock1, lock2; lock1 = getlock(from); lock2 = getlock(to); acquire(lock1); acquire(lock2); with

在下面的代码中,如果两个线程同时调用
transaction()
函数,转换不同的帐户,则可能出现死锁

void transaction(Account from, Account to, double amount)
{
      mutex lock1, lock2;
      lock1 = getlock(from);
      lock2 = getlock(to);

      acquire(lock1);
      acquire(lock2);
         withdraw(from, amount);
         deposit(to, amount);
      release(lock2);
      release(lock1);
}
也就是说,一个线程可以调用

transaction(checkingaccount, savingsaccount, 25);
transaction(savingsaccount, checkingaccount, 50);
另一个可能会调用

transaction(checkingaccount, savingsaccount, 25);
transaction(savingsaccount, checkingaccount, 50);
解决这个问题的好办法是什么

我能想到的一个方法是使用一个见证程序来提醒用户死锁已经发生,但是必须有一个更好的解决方案可以通过修改代码来实现。有什么想法吗


附:这是一本关于操作系统的教科书。这不是家庭作业,只是死锁章节的一部分。

这是第10.1.2项“动态锁顺序死锁”中描述的一个问题(以及解决方案),它是专门为Java编写的,但逻辑可以很好地应用于其他上下文(如您的上下文)

因此,由于我们无法控制参数的提供顺序,我们需要对锁进行排序,并在我们编写的整个程序中一致地根据导出的顺序获取它们

归纳该顺序的一种方法是计算
from
to
对象的散列码,并同步首先从散列码较低的对象获取锁。在两个
Account
对象具有相同哈希代码的(罕见)情况下,我们需要引入第三个锁,这将“打破”这一联系

例如,在Java中,它将是:

int fromHash = System.identityHashCode(from);
int toHash = System.identityHashCode(to);

现在,以您的代码作为参考,它可能类似于下面的代码

Object objectForTieBreakerLock = new Object(); // a valid new object here according to your language
void transaction(Account from, Account to, double amount)
{
      mutex lock1, lock2, tieBreaker;
      lock1 = getlock(from);
      lock2 = getlock(to);

      int fromHash = /*any language specific function to get object hash*/;
      int toHash = /*any language specific function to get object hash*/;

      if (fromHash < toHash) {
          acquire(lock1);
          acquire(lock2);
          doTransaction(from, to, amount);
          release(lock2);
          release(lock1);
      }
      else if (fromHash > toHash) {
          acquire(lock2);
          acquire(lock1);
          doTransaction(from, to, amount);
          release(lock1);
          release(lock2);
      }
      else {
          tieBreaker = getlock(objectForTieBreakerLock);
          acquire(tieBreaker);
          acquire(lock1);
          acquire(lock2);
          doTransaction(from, to, amount);
          release(lock2);
          release(lock1);
          release(tieBreaker);
      }
}

// this must be a private (helper) method
void doTransaction(Account from, Account to, double amount)
{
     withdraw(from, amount);
     deposit(to, amount);
}
objectobjectforitebreakerlock=newobject();//根据您的语言,这里有一个有效的新对象
无效交易记录(账户起始、账户终止、双倍金额)
{
互斥锁1、锁2、分接开关;
lock1=getlock(来自);
lock2=getlock(to);
int fromHash=/*用于获取对象哈希的任何特定于语言的函数*;
int toHash=/*用于获取对象哈希的任何特定于语言的函数*;
if(fromHash到哈希){
获取(锁2);
获取(锁1);
doTransaction(从、到、金额);
释放(锁1);
释放(锁2);
}
否则{
tieBreaker=getlock(objectforitebreakerlock);
获取(平局破坏者);
获取(锁1);
获取(锁2);
doTransaction(从、到、金额);
释放(锁2);
释放(锁1);
释放(断开连接);
}
}
//这必须是私有(助手)方法
作废DotTransaction(账户起始、账户至、双倍金额)
{
提取(从,金额);
押金(至、金额);
}

附加说明

  • 如果
    Account
    具有唯一的、不可变的、可比较的密钥,例如唯一的数字、标识符或类似的东西,则诱导锁排序将更容易:按其密钥对对象进行排序,这样就不需要
    tieBreaker

  • 完整Java代码示例: