线程内的死锁
Deadlock within threads
所以我的系统中有一个死锁,我一辈子都不知道它在哪里。
本质上,在我的系统中,我有一个由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
更大,则可以通过交换randlane1
和randlane2
来解决此问题,这将确保在大多数情况下,锁是按递增顺序获得的。当然,您还必须添加更多的逻辑来处理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。
- 用C++中的std::condition_variable将线程置于死锁中会有风险吗
- localtime() 函数正在调用 ___lll_lock_wait_private(),这会使线程陷入死锁
- Qt:向死/停止线程发送信号
- 多线程Windows GUI应用程序中的死锁
- 死锁使用 std::mutex 来保护多个线程中的 cout
- 一个线程提升的死锁
- 是否访问指针元组和互斥锁线程安全
- C++互斥锁线程优先级
- 解决死锁问题,在主线程中等待多个工作线程完成 (C++11)
- 为什么我的程序在拥有线程的情况下生成LdrpLoaderLock死锁
- 避免单个线程中的死锁
- 这个简单的(原子)锁线程安全吗
- 线程tcp服务器死锁
- 线程安全std::cout的死锁
- 提升线程死锁,任何人都可以检查原因
- 如何在 QT 中使用互斥锁线程开始轮询
- 无锁线程池
- FFMPEG:多线程解码死锁
- 如何在C++Qt程序中调试多线程死锁
- 这种类型的编码是线程安全的还是死锁安全的