线程内的死锁

时间:2015-11-10 10:20:25

标签: c++ multithreading deadlock

所以我的系统内部陷入僵局,而且在我的生命中,我无法弄清楚它的位置。

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

只有每个线程看一个元素,没有死锁,但每个线程看两个元素,很有可能出现死锁。

这是我的代码:

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]);


}

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

3 个答案:

答案 0 :(得分:1)

代码的这一部分:

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;
}

答案 1 :(得分:0)

Chris Maes已经解决了部分问题 - randlane1 == randlane2的问题 - 但即使解决了这个问题,你的程序仍然会陷入僵局。

另一个更微妙的问题是你获得锁定的顺序。

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

此时,线程A将尝试获取锁定5(由于线程B具有锁定,因此将阻塞),并且线程B将尝试获取锁定4(由于线程A具有锁定,因此将阻塞)。现在两个线程都无法取得任何进展。

对此的解决方案是您必须始终在所有线程中以相同的顺序获取锁。这意味着你必须定义一个锁定的顺序(对于这个例子,数字顺序是有意义的),并且永远不要尝试获取锁定,同时保持顺序中稍后出现的另一个锁。

在此示例中,您可以通过交换randlane1randlane2来解决问题,如果事实证明randlane1更大 - 这将确保在大多数情况下,锁定是按升序获得。当然,您还需要添加更多逻辑来应对randlane1 == randlane2

的情况

答案 2 :(得分:0)

你获得锁定的方式已经成熟,可以解决僵局。

两线程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正在等待lock2(并持有lock1) 线程2正在等待lock1(并持有lock2)。

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

因此,如果您持有锁4并锁定5.然后您选择已经使用5并且您随机选择锁1来替换它。然后你必须释放4和5并按顺序获得锁1和。