Multithreading 在单个线程上是否可能出现死锁?
常见的筛选面试问题是:达到死锁所需的最少线程数是多少 正确答案是2Multithreading 在单个线程上是否可能出现死锁?,multithreading,theory,Multithreading,Theory,常见的筛选面试问题是:达到死锁所需的最少线程数是多少 正确答案是2 但从理论上讲,使用一个线程就可以产生死锁吗?根据死锁的定义: 死锁是一种状态,其中一组操作的每个成员 等待其他成员释放锁 只有一个线程无法达到死锁状态 对于单线程,您可能会遇到无限循环 如果我们将协程考虑在内,单线程应用程序确实可能会遇到死锁的情况。大卫·施瓦茨提到了这一点 这完全取决于您如何定义“线程”。例如,考虑使用协同程序处理请求的单线程服务器。一个请求的协同路由可能持有另一个线程的协同路由所需的锁,反之亦然。两个协同程序
但从理论上讲,使用一个线程就可以产生死锁吗?根据
死锁的定义:
死锁是一种状态,其中一组操作的每个成员
等待其他成员释放锁
只有一个线程无法达到死锁状态
对于单线程,您可能会遇到无限循环
如果我们将协程考虑在内,单线程应用程序确实可能会遇到死锁的情况。大卫·施瓦茨提到了这一点
这完全取决于您如何定义“线程”。例如,考虑使用协同程序处理请求的单线程服务器。一个请求的协同路由可能持有另一个线程的协同路由所需的锁,反之亦然。两个协同程序都不能向前推进,除非另一个能够向前推进
你考虑那些协同程序执行上下文线程吗?是不是?
这里有一个单线程程序,由于pthreads互斥体(默认情况下)是:
#包括
#包括
int main(int,char**)
{
pthread_mutex_t m;
pthread_mutex_init(&m,NULL);
printf(“锁定非递归互斥锁一次…\n”);
pthread_mutex_lock(&m);
printf(“再次锁定非递归互斥…\n”);
pthread_mutex_lock(&m);//这里会发生死锁,因为我们会一直等待锁定的互斥锁解锁。。。
printf(“您永远不会看到打印的文本,因为我们将在上面陷入僵局\n”);
返回0;
}
(如果将互斥体设置为递归互斥体,OTOH,则此场景将由互斥体处理,并将避免死锁)考虑以下代码片段:
#include<signal.h>
some_struct data;
int main(){
sigset(SIGINT, handler);
computation_fn();
return 0;
}
computation_fn(){
pthread_mutex_lock(&m);
update_state(&data);
pthread_mutex_unlock(&m);
}
void handler(int signo){
pthread_mutex_lock(&m);
display_state(&data);
pthread_mutex_unlock(&m);
}
#包括
一些结构化数据;
int main(){
sigset(SIGINT,handler);
计算_fn();
返回0;
}
计算_fn(){
pthread_mutex_lock(&m);
更新_状态(和数据);
pthread_mutex_unlock(&m);
}
无效处理程序(int signo){
pthread_mutex_lock(&m);
显示_状态(&U)数据;
pthread_mutex_unlock(&m);
}
- 在上面的代码段中,数据由处理程序访问以显示
因此可以通过互斥来访问。对于更新,它还需要
计算_fn()中的互斥体
- 现在考虑CudioTyfn()是否需要很长的时间来执行
用户决定提交CNTRL-C,则处理程序()将
执行。因为锁不会从系统中释放
计算_fn(),它将无限期地等待它可用
- 此外,由于在处理程序使用(借用)与计算线程相同的线程时,程序中没有其他线程从计算线程释放互斥体,因此无法释放此互斥体
最终我们可以看到,通过这种方式,单线程程序可以进入死锁死锁意味着资源图中的一个循环。这样的循环可以使用单线程创建,例如
Thread.currentThread().join();
没有任何东西可以阻止单个线程创建互斥体,然后阻止互斥体,但这可能不被认为是死锁。这可能发生在.NET中使用async/await和Task之前,发生在具有同步上下文的线程上。如果使用GOTOs语言,那么我的猜测可能是肯定的:在等待之前跳回标签()你完成了。但是它依赖于语言,而不是在所有上下文中都有效,所以…如果操作组的成员不是线程,而是由单个线程执行的函数呢?例如,考虑两个协同进程在一个线程中运行,每个线程都持有一个锁,另一个线程需要向前推进。为什么这不是僵局?为什么需要多个线程?@DavidSchwartz,对。我同意。如果我们认为协同程序是单线程的。那么,是的。它可以到达死锁。
Thread.currentThread().join();