线程内的死锁

Deadlock within threads

本文关键字:死锁 线程      更新时间:2023-10-16

所以我的系统中有一个死锁,我一辈子都不知道它在哪里。

本质上,在我的系统中,我有一个由12个元素和12个对应于每个元素的锁组成的阵列。然后,我有两个线程来创建一个函数,该函数对数组执行计算。但是每个线程一次在数组中执行两个元素更改。

每个线程只看一个元素,就不会出现死锁,但每个线程看两个元素,出现死锁的可能性很小。

这是我的代码:

Thread() {
           - some other code that doesnt effect the threads -
           // randomly pick a lane between 0 - 15
           randLane1 = rand() % 16;
           randLane2 = rand() % 16;
           pthread_mutex_lock(&mutexFineLock[randLane1]);
           pthread_mutex_lock(&mutexFineLock[randLane2]);
           // if Rouge picked a lane that has already been fired at, look for a free lane
           while(Gallery->Get(randLane1) != white) {
              pthread_mutex_unlock(&mutexFineLock[randLane1]);
              randLane1 = rand() % 16;
              pthread_mutex_lock(&mutexFineLock[randLane1]);
           }
           while(Gallery->Get(randLane2) != white || randLane2 == randLane1) {
              pthread_mutex_unlock(&mutexFineLock[randLane2]);
              randLane2 = rand() % 16;
              pthread_mutex_lock(&mutexFineLock[randLane2]);
           }
           // set the lane's colour
           Gallery->Set(randLane1, PlayerColor);
           Gallery->Set(randLane2, PlayerColor);
           // set the thread to wait X amount of time to simulate a shot        
           usleep(1000000/rate);
           // upon lock for other threads
           pthread_mutex_unlock(&mutexFineLock[randLane1]);
           pthread_mutex_unlock(&mutexFineLock[randLane2]);

}

如果有人能够准确定位死锁发生的位置,那将是最有帮助的。如果您需要我进一步澄清系统,请询问。

在代码的这一部分中:

while(Gallery->Get(randLane2) != white || randLane2 == randLane1) {
    pthread_mutex_unlock(&mutexFineLock[randLane2]);
    randLane2 = rand() % 16;
    pthread_mutex_lock(&mutexFineLock[randLane2]);
}

当randLand2==randlane1时;

pthread_mutex_lock(&mutexFineLock[randLane2]);

永远不会成功,因为互斥锁已经被锁定。为了避免这个问题;你可以考虑做一些类似的事情:

int lockAcquired = 0;
while(!lockAcquired && Gallery->Get(randLane2) != white || randLane2 == randLane1) {
    pthread_mutex_unlock(&mutexFineLock[randLane2]);
    randLane2 = rand() % 16;
    if (pthread_mutex_trylock(&mutexFineLock[randLane2]))
        lockAcquired = 1;
}

Chris Maes已经解决了部分问题——randlane1 == randlane2的问题——但即使解决了这个问题,您的程序仍然可能死锁。

另一个更微妙的问题是与获取锁的顺序有关。

假设线程A决定它将获取锁4&5,并且同时线程B决定它将获取锁5&4.线程A将首先获得锁4,线程B将首先获得锁定5。

在这一点上,线程A将尝试获得锁5(由于线程B具有它,它将被阻塞),线程B将尝试获得锁定4(由于线程A具有它,所以它将被阻止)。现在,两个线程都无法取得任何进展。

解决方法是,必须始终在所有线程中以相同的顺序获取锁。这意味着您必须为锁定义一个顺序(在本例中,数字顺序是有意义的),并且永远不要在持有顺序后面的另一个锁的同时试图获得一个锁。

在本例中,如果randlane1更大,则可以通过交换randlane1randlane2来解决此问题,这将确保在大多数情况下,锁是按递增顺序获得的。当然,您还必须添加更多的逻辑来处理randlane1 == randlane2的情况。

获取锁的方式适合死锁。

双线程senario

 Thread1                            Thread2
 =================                  =================
 lock1 = 1;                        
 lock2 = 2;
                                    lock1 = 2;
                                    lock2 = 1;
 mutex_lock(&array[lock1]);
                                    mutex_lock(&array[lock1]);
 mutex_lock(&array[lock2]);
                                    mutex_lock(&array[lock2]);

这里你陷入僵局
线程1正在等待锁定2(并保持锁定1)
线程2正在等待锁定1(并保持锁定2)。

持有多个锁的方法是必须按顺序获取这些锁。如果您释放并尝试获取新锁,则必须再次确保这些锁仍然按顺序获取。

如果你拿着锁4和锁5。然后你选择5已经被使用,你随机选择锁1来替换它。然后你必须释放4和5,并按顺序获得锁1和4。