2013-08-04 114 views
3

几个星期前我有一堂课,我的解决方案很好,但是当观察它更长时间时,我注意到了一些奇怪的行为。 该练习使用两个posix线程产生死锁,然后解决它。 (我抽象的解决方案,因此它没有任何不必要的代码解决死锁时的奇怪行为

的场景如下:

  • 我有谁共享两个虚构的资源两个线程
  • 两个线程启动序列,然后设法占领这两个资源(按顺序太)
  • 两个线程都拥有占领
  • 当一个线程都有他的作品持续5秒两种资源不同的时间跨度,然后释放该资源,并在他再次开始需要休息,当断则试图占据这两个资源
  • 每8秒功能checkes如果两个线程都等待状态(这两个线程都一个资源,并等待第二次)
  • 死锁时occures,谁的工作更线程得到取消,然后重新启动

问题出在这里,这取决于机器和编译器标记输出说,例如线程A被取消,但线程B启动。我用不同的编译器在不同的计算机上试过它,并使用不同的关系。 奇怪的是,我编译gcc -Wall -Werror -ansi -pedantic -D_POSIX_C_SOURCE=200809L -pthread -lrt,并与第二死锁问题occures,但是当我删除-Wall和-Werror问题自带的3僵局0O

我上传的源here。编译标志位于源代码中,我尝试了gcc和clang。 我也试过Ubuntu 13.04和Arch。
Here是输出,我用“ - >”标记了行

我忘记了一些东西,所以这个效果出现了吗?我不认为在某些库中有错误。

+0

我没有得到你同样的效果。你可以发布你看到的输出吗? –

回答

1

问题是你正在传递一个局部变量的地址给线程。而且这个局部变量在线程启动时可能不再存在,并且您正在取消引用使用来保存局部变量但现在包含其他内容的地址位置。

由于它在程序的堆栈空间中,所以没有收到段错误。

这里是代码的问题领域的一个亮点,它如何被引起的:

void resolve_deadlock() 
{ 
    void *pthread_exit_state; 
    int id_a = THREAD_A; 
    int id_b = THREAD_B; 

    <some code to detect deadlocks and kill a thread> 

/* restart the killed thread */ 
if (pthread_create(&threads[THREAD_B], NULL, &thread_function, (void *) &id_b) != 0) { 
        perror("Create THREAD_B\n"); 
        exit(EXIT_FAILURE); 
      } 
} 

因此程序运行和:

  1. resolve_deadlock叫
  2. 线X被杀害
  3. 在pthread_create被调用来创建一个线程
  4. resolve_deadlock函数结束
  5. 堆栈在旁边函数调用
  6. 操作系统交换我们出去,并运行另一个线程
  7. 线程X运行,并取消引用不再存在我们的局部变量写 - >未定义的行为。
+0

所以我假设让id_a和id_b全局解决错误?我可以发誓我昨天晚上试过,它仍然存在,但我现在再试一次,它似乎工作0(也许我昨天忘了一些事情) 但你有一个想法,为什么我得到不同的行为,当我删除 - 墙和 - 错误标志?他们似乎只是设置编译器输出而不改变编译。 – a2r

+0

还有没有其他方式解决这个问题,而不是使变量全球? – a2r

+0

您看到的不同行为是由于线程的计划时间所致。如果你多次运行相同的编译程序,那么你会在不同的运行中看到错误(有时候本地var会存在,有时它不会)。 – dave