将两个或多个互斥量应用于一段代码
Applying two or more mutexes to a section of code
我正在研究来自 http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
的 c++ pthreads 中的互斥锁和死锁
我理解他们,但我在一个点上堆了起来。我不明白下面代码的问题是什么。你能用简单明了的话解释一下吗?我从这个网站引用:
互斥锁死锁:...将两个或多个互斥锁应用到一段代码时要小心。如果第一个 pthread_mutex_lock 被应用并且第二个 pthread_mutex_lock 由于另一个线程应用互斥锁而失败,则第一个互斥锁最终可能会锁定所有其他线程访问数据,包括持有第二个互斥锁的线程。线程可能会无限期地等待资源空闲,从而导致死锁。最好进行测试,如果失败,请释放资源并在重试前暂停。
01 ...
02 pthread_mutex_lock(&mutex_1);
03 while ( pthread_mutex_trylock(&mutex_2) ) /* Test if already locked */
04 {
05 pthread_mutex_unlock(&mutex_1); /* Free resource to avoid deadlock */
06 ...
07 /* stall here */
08 ...
09 pthread_mutex_lock(&mutex_1);
10 }
11 count++;
12 pthread_mutex_unlock(&mutex_1);
13 pthread_mutex_unlock(&mutex_2);
14 ...
提前致谢。
本质上如果你需要两个互斥量来执行一个任务,mutex_1
和mutex_2
,如果thread_A
抓取mutex_1
并且thread_B
抓取mutex_2
,他们陷入了死锁,因为他们都在等待另一个互斥体可用,但他们永远不会,因为另一个也在等待。
这就是为什么您通常强制执行可以获取互斥锁的命令。例如,您必须在尝试获取 mutex_2
之前获取 mutex_1
。这样你就不能在没有先有 mutex_1
的情况下有 mutex_2
,所以没有机会造成死锁。
Thread_A Thread_B
| |
| |
lock(mutex_1) | // Thread_A got mutex_1
| |
| lock(mutex_2) // Thread_B got mutex_2
| |
| |
trylock(mutex_2) | // Thread_A wants mutex_2
| trylock(mutex_1) // Thread_B wants mutex_1
| |
由于时间原因,这些线程现在处于死锁状态。两者都在等待他们永远不会得到的互斥锁,因为另一个线程在完成其工作之前不会解锁它持有的互斥锁。
在您的代码示例中,请注意他们做的第一件事是锁定 mutex_1
。然后他们旋转 mutex_2
直到它可用。这是执行命令 mutex_1
然后 mutex_2
.
如果您锁定一个互斥体,然后等待第二个,第一个仍处于锁定状态,因此在您等待期间其他人无法获得它。这很糟糕,所以也许在你等待的时候解锁第一个互斥体。该代码显示了如何执行此操作。
如果另一个线程拥有您正在等待的互斥锁,并且需要您的互斥锁(它不应该这样,除非设计被搞砸了),那将是非常糟糕的——两个线程将永远等待,导致"deadlock" - 你肯定需要在等待时解锁第一个。
但在那种情况下,您应该正确修复它(如下一节所述)- 始终以明确定义的顺序锁定两个互斥体。
我正在研究来自 http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
的 c++ pthreads 中的互斥锁和死锁我理解他们,但我在一个点上堆了起来。我不明白下面代码的问题是什么。你能用简单明了的话解释一下吗?我从这个网站引用:
互斥锁死锁:...将两个或多个互斥锁应用到一段代码时要小心。如果第一个 pthread_mutex_lock 被应用并且第二个 pthread_mutex_lock 由于另一个线程应用互斥锁而失败,则第一个互斥锁最终可能会锁定所有其他线程访问数据,包括持有第二个互斥锁的线程。线程可能会无限期地等待资源空闲,从而导致死锁。最好进行测试,如果失败,请释放资源并在重试前暂停。
01 ...
02 pthread_mutex_lock(&mutex_1);
03 while ( pthread_mutex_trylock(&mutex_2) ) /* Test if already locked */
04 {
05 pthread_mutex_unlock(&mutex_1); /* Free resource to avoid deadlock */
06 ...
07 /* stall here */
08 ...
09 pthread_mutex_lock(&mutex_1);
10 }
11 count++;
12 pthread_mutex_unlock(&mutex_1);
13 pthread_mutex_unlock(&mutex_2);
14 ...
提前致谢。
本质上如果你需要两个互斥量来执行一个任务,mutex_1
和mutex_2
,如果thread_A
抓取mutex_1
并且thread_B
抓取mutex_2
,他们陷入了死锁,因为他们都在等待另一个互斥体可用,但他们永远不会,因为另一个也在等待。
这就是为什么您通常强制执行可以获取互斥锁的命令。例如,您必须在尝试获取 mutex_2
之前获取 mutex_1
。这样你就不能在没有先有 mutex_1
的情况下有 mutex_2
,所以没有机会造成死锁。
Thread_A Thread_B
| |
| |
lock(mutex_1) | // Thread_A got mutex_1
| |
| lock(mutex_2) // Thread_B got mutex_2
| |
| |
trylock(mutex_2) | // Thread_A wants mutex_2
| trylock(mutex_1) // Thread_B wants mutex_1
| |
由于时间原因,这些线程现在处于死锁状态。两者都在等待他们永远不会得到的互斥锁,因为另一个线程在完成其工作之前不会解锁它持有的互斥锁。
在您的代码示例中,请注意他们做的第一件事是锁定 mutex_1
。然后他们旋转 mutex_2
直到它可用。这是执行命令 mutex_1
然后 mutex_2
.
如果您锁定一个互斥体,然后等待第二个,第一个仍处于锁定状态,因此在您等待期间其他人无法获得它。这很糟糕,所以也许在你等待的时候解锁第一个互斥体。该代码显示了如何执行此操作。
如果另一个线程拥有您正在等待的互斥锁,并且需要您的互斥锁(它不应该这样,除非设计被搞砸了),那将是非常糟糕的——两个线程将永远等待,导致"deadlock" - 你肯定需要在等待时解锁第一个。
但在那种情况下,您应该正确修复它(如下一节所述)- 始终以明确定义的顺序锁定两个互斥体。