pthread_join死锁的简单示例

时间:2016-03-19 20:01:25

标签: c multithreading pthreads deadlock pthread-join

我正在寻找一个使用pthread_join演示死锁的简单示例;然而,这并非无足轻重。

我从这开始:

void* joinit(void* tid)
{
  pthread_t* tid_c = (pthread_t*)tid;
  int retval = pthread_join(*tid_c, NULL);
  printf("In joinit: tid = %d, retval = %d \n", *tid_c, retval);
  return NULL;
}

int main()
{
  pthread_t thread1;
  pthread_t thread2;

  pthread_create(&thread1, NULL, joinit, &thread2);
  pthread_create(&thread2, NULL, joinit, &thread1);

  pthread_join(thread2, NULL);  

  return 0;
}

但是,它说'EINVAL' (无效参数),因为在调用thread2的{​​{1}}时尚未指定pthread_create

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

如果您只想证明pthread_join可能导致死锁,您可以执行类似以下代码的操作:

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

void* joinit(void* tid)
{
    printf("In %#x, waiting on %#x\n", pthread_self(), (*((pthread_t*)tid)));
    pthread_join((*((pthread_t*)tid)), NULL);
    printf("Leaving %#x\n", pthread_self());
    return NULL;
}

int main(void)
{
    pthread_t thread1 = pthread_self();
    pthread_t thread2;
    pthread_create(&thread2, NULL, joinit, &thread1);
    joinit(&thread2);
    return 0;
}

这将导致主线程在生成的线程上等待,并且生成的线程在主线程上等待(导致保证死锁),而不需要额外的锁定原语来混淆你想要演示的内容。

更直接地回答您的一些问题:

  

它显示'EINVAL'(无效参数),因为在调用thread2的{​​{1}}时尚未指定pthread_create

......并从你的一条评论中......

  

我试过这个并且它有效,但问题是,它只能起作用,因为有时候我会再次获得EINVAL。

在你的代码中,你连续调用thread1来产生2个线程:

pthread_create

pthread_create(&thread1, NULL, joinit, &thread2); pthread_create(&thread2, NULL, joinit, &thread1); 代码中,您获取传入的线程句柄以加入:

joinit

这个有时的工作原理和其他你得到pthread_t* tid_c = (pthread_t*)tid; int retval = pthread_join(*tid_c, NULL); 的原因与分配给每个线程的上下文time slicessequencing有关。调用第一个EINVAL后,pthread_create返回后会有thread1的有效句柄,但thread2的句柄无效,至少直到第二个pthread_create叫做。

为此,当创建一个线程时,即使返回的线程句柄有效,线程的“活动”行为(即实际运行的线程函数)也可能需要一些额外的时间。在这些情况下,一个线程有可能执行比“预期”更多的代码。在你的代码中,两个pthread_create函数可能恰好在为主线程分配的时间片中被调用,可以为每个生成的线程提供足够的“时间”在点击允许pthread_join指向有效句柄的tid_c语句之前;在EINVAL案例中,调用了pthread_create(&thread1, NULL, joinit, &thread2),并且 pthread_join(*tid_c, NULL)生成后的线程点击了pthread_create(&thread2, NULL, joinit, &thread1) ,可以为thread2提供有效句柄(导致错误)。

如果你想保持你的代码与现在的代码类似,你需要添加某种锁以确保线程不会退出或过早地调用任何东西:

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

static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

void* joinit(void* tid)
{
    /* this can be above the lock because it will be valid after lock is acquired */
    pthread_t* tid_c = (pthread_t*)tid;
    int retval = -1;
    pthread_mutex_lock(&lock);
    pthread_mutex_unlock(&lock);
    printf("%#x waiting on %#x\n", pthread_self(), *tid_c);
    retval = pthread_join(*tid_c, NULL);
    printf("In joinit: tid = %d, retval = %d \n", *tid_c, retval);
    return NULL;
}

int main()
{
    pthread_t thread1;
    pthread_t thread2;
    /* get the lock in the main thread FIRST */
    pthread_mutex_lock(&lock);
    pthread_create(&thread1, NULL, joinit, &thread2);
    pthread_create(&thread2, NULL, joinit, &thread1);
    /* by this point, both handles are "joinable", so unlock  */
    pthread_mutex_unlock(&lock);

    /* can wait on either thread, but must wait on one so main thread doesn't exit */
    pthread_join(thread2, NULL);
    return 0;
}

希望这可以提供帮助。

答案 1 :(得分:0)

您的错误的主要原因是,由于height.bashrc的调用,您有两个线程,每个线程等待同一个线程终止。另一个问题是你不能确保每个线程正确地看到另一个线程的ID。

修复如下:

pthread_join