是否有可能在单个线程上达成死锁?

时间:2017-07-01 21:55:15

标签: multithreading theory

流行的筛选面试问题是:达到死锁所需的最小线程数是多少?

正确答案是2。

但理论上是否可以使用一个单独的线程来解决死锁?

5 个答案:

答案 0 :(得分:1)

这取决于你如何定义" thread"。例如,考虑使用协同程序处理请求的单线程服务器。一个请求的协程可能会保存另一个线程的协程所需的锁,反之亦然。协同程序都不能直到另一个程序才能取得进展。

你认为那些协同执行上下文线程吗?或者不是?

答案 1 :(得分:1)

这是一个死锁的单线程程序,因为pthreads互斥锁是(默认情况下)http://www.w3.org/2000/xmlns/

#include <stdio.h>
#include <pthread.h>

int main(int, char **)
{  
   pthread_mutex_t m;
   pthread_mutex_init(&m, NULL);

   printf("Locking non-recursive mutex once...\n");
   pthread_mutex_lock(&m);

   printf("Locking non-recursive mutex again...\n");
   pthread_mutex_lock(&m);   // deadlock occurs here, as we wait forever for the locked mutex to be unlocked...

   printf("You won't ever see this text printed, because we'll be deadlocked above\n");

   return 0;
}

(如果将互斥锁设置为递归互斥锁OTOH,则此方案将由互斥锁处理并避免死锁)

答案 2 :(得分:0)

根据deadlock的定义:https://en.wikipedia.org/wiki/Deadlock

  

死锁是一组操作中每个成员的状态   等待其他成员释放锁定。

只用一个线程就无法达到死锁状态。

对于单线程,您可能会遇到infinite loophttps://en.wikipedia.org/wiki/Infinite_loop

  

如果我们考虑包含协同程序,单线程应用程序确实会遇到死锁情况。这是@David Schwartz提到的。

答案 3 :(得分:0)

请考虑以下代码段:

  #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);
  }
  • 在以上代码段中,处理程序将访问数据以进行显示 因此可以通过互斥锁访问。为了更新也需要 计算_fn()中的互斥体。
  • 现在考虑是否要执行Calculation_fn()花费很长时间,并且 用户决定提交CNTRL-C,然后handler()将是 被执行。由于锁不会从 Calculation_fn(),它将无限等待它可用。
  • 此外,由于处理程序使用(借用)与computing_fn()相同的线程,因此程序中没有其他线程可以从compute_fn()释放互斥量,所以也就没有办法释放此互斥量。 li>

最终,我们可以看到单线程程序可以进入死锁

答案 4 :(得分:0)

死锁意味着资源图中的循环。这样的循环可以使用单线程创建,例如

    Thread.currentThread().join();