所以我的系统内部陷入僵局,而且在我的生命中,我无法弄清楚它的位置。
基本上在我的系统中,我有一个由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]);
}
如果有人能够确定死锁发生的位置,那将是最有帮助的。如果您需要我更多地澄清系统,请询问。
答案 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具有锁定,因此将阻塞)。现在两个线程都无法取得任何进展。
对此的解决方案是您必须始终在所有线程中以相同的顺序获取锁。这意味着你必须定义一个锁定的顺序(对于这个例子,数字顺序是有意义的),并且永远不要尝试获取锁定,同时保持顺序中稍后出现的另一个锁。
在此示例中,您可以通过交换randlane1
和randlane2
来解决问题,如果事实证明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和。