1

我是多线程的新手,因此从一个小程序开始。程序的预期工作是,通过两个线程一个接一个地打印整数,这样一个线程应该打印一个数字,另一个线程应该打印下一个数字,这个过程应该继续直到定义的最大数字.

为此,我编写了一个小程序并且面临死锁。我尝试使用 gdb 查找互斥锁所有者,但它只是在执行 print mutex 命令时打印 $3 = 2。

这是源代码:

#include <iostream>
#include <fstream>
#include <pthread.h>
#include <signal.h>

const int MAX_NUM = 13;

pthread_cond_t cond[1] = {PTHREAD_COND_INITIALIZER,};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int Count = 0;

using namespace std;

void* thread1(void*)
{
    do {
        cout<<"inside thread 1 abt to acquire lock"<<endl;
        // Increment counter in thread1
        pthread_mutex_lock(&mutex);
        cout<<"inside thread 1 blocked"<<endl;
        pthread_cond_wait(&cond[0],&mutex);
        cout<<"after pthread_cond_wait in thread1"<<endl;
        pthread_cond_signal(&cond[1]);
        if(Count < MAX_NUM)
        {
            Count++;
            pthread_mutex_unlock(&mutex);
            cout<<"Printing from thread 1"<<endl;
            cout<<Count<<endl;
        }
        else
        {
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }
    }while(1);
 }

 void* thread2(void*)
 {
     do{
         cout<<"inside thread 2 abt to acquire lock"<<endl;
         pthread_mutex_lock(&mutex);
         cout<<"inside thread 2 blocked"<<endl;
         pthread_cond_wait(&cond[1],&mutex);
         // Increment counter in thread2
         pthread_cond_signal(&cond[0]);
         if(Count < MAX_NUM)
         {
             Count++;
             pthread_mutex_unlock(&mutex);
             cout<<"Printing from thread 2"<<endl;
             cout<<Count<<endl;
         }
         else
         {
             pthread_mutex_unlock(&mutex);
             pthread_exit(NULL);
         }
    }while(1);
}

int main()
{
    pthread_t t[2];
    void* (*fun[2])(void*);
    fun[0]=thread1;
    fun[1]=thread2;

    for (int i =0 ; i < 2; ++i)
    {
        pthread_create(&t[i],NULL,fun[i],NULL);
    }
    cout<<"threads created"<<endl;

    pthread_cond_signal(&cond[0]);

    cout<<"In main after sending signal"<<endl;


    pthread_join(t[0],NULL);
    pthread_join(t[1],NULL);

    pthread_exit(NULL);
}

输出是:
在线程 1 内部 abt 获取锁
在线程 1 内部被阻塞
在线程 2 内部 abt 在线程 2 内部获取锁 在发送信号后在 main 中 创建
阻塞线程


我希望 main() 线程向线程 1 发送信号,线程 1 完成它的工作(即更新计数器),然后将信号传递给线程 2,线程 2 完成它的工作(即更新计数器)并将信号传递给线程 1。这个过程应该一直持续到达到最大数量。如果达到最大数量,每个进程都会解锁互斥锁并正常退出。

请帮我。我真的尝试了很多都没有奏效。

4

2 回答 2

2

线

pthread_cond_t cond[1] = {PTHREAD_COND_INITIALIZER,};

定义了一个大小为 1 的数组,但稍后您使用cond[1],数组中的第二个条目,它是未定义的。你的意思

pthread_cond_t cond[2] = {PTHREAD_COND_INITIALIZER,PTHREAD_COND_INITIALIZER};

这看起来像是一个不幸的错字。(由于前文MAX_NUM = 13?)

于 2013-07-19T22:32:48.333 回答
1

In addition to @TooTone's observation you need to understand one aspect of how condition variables work. If you signal a condition variable when no thread is blocked on it nothing will happen. The condition variable has no memory, so if a little bit later a thread blocks on in it will stay locked until the condition is signaled again.

Your main function signals cond[0] right after it started the threads, so it is possible that the threads haven't reached their blocking point yet. Or if they are blocked then it can happen that when one thread signals the other one that other one isn't blocked. So after you fix your condition variable array you will see that the test runs a bit more, but eventually deadlocks again.

I was able to make it work using a quick & dirty trick of introducing delays before signaling the condition variables. This gives the threads time to reach their blocking points before the signaling happens. Here is the modified code:

const int MAX_NUM = 13;

pthread_cond_t cond[2] = {PTHREAD_COND_INITIALIZER,PTHREAD_COND_INITIALIZER};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int Count = 0;

using namespace std;

void* thread1(void*)
{
    do {
        cout<<"inside thread 1 abt to acquire lock"<<endl;
        // Increment counter in thread1
        pthread_mutex_lock(&mutex);
        cout<<"inside thread 1 blocked"<<endl;
        pthread_cond_wait(&cond[0],&mutex);
        cout<<"after pthread_cond_wait in thread1"<<endl;
        if(Count < MAX_NUM)
        {
            Count++;
            pthread_mutex_unlock(&mutex);
            cout<<"Printing from thread 1"<<endl;
            cout<<Count<<endl;
            usleep(1000000);
            pthread_cond_signal(&cond[1]);
        }
        else
        {
            pthread_mutex_unlock(&mutex);
            usleep(1000000);
            pthread_cond_signal(&cond[1]);
            pthread_exit(NULL);
        }
    }while(1);
 }

 void* thread2(void*)
 {
     do{
         cout<<"inside thread 2 abt to acquire lock"<<endl;
         pthread_mutex_lock(&mutex);
         cout<<"inside thread 2 blocked"<<endl;
         pthread_cond_wait(&cond[1],&mutex);
         // Increment counter in thread2
         if(Count < MAX_NUM)
         {
             Count++;
             pthread_mutex_unlock(&mutex);
             cout<<"Printing from thread 2"<<endl;
             cout<<Count<<endl;
             usleep(1000000);
             pthread_cond_signal(&cond[0]);
         }
         else
         {
             pthread_mutex_unlock(&mutex);
             usleep(1000000);
             pthread_cond_signal(&cond[0]);
             pthread_exit(NULL);
         }
    }while(1);
}

int main()
{
    pthread_t t[2];
    void* (*fun[2])(void*);
    fun[0]=thread1;
    fun[1]=thread2;

    for (int i =0 ; i < 2; ++i)
    {
        pthread_create(&t[i],NULL,fun[i],NULL);
    }
    cout<<"threads created"<<endl;
    usleep(1000000);
    pthread_cond_signal(&cond[0]);

    cout<<"In main after sending signal"<<endl;


    pthread_join(t[0],NULL);
    pthread_join(t[1],NULL);

    pthread_exit(NULL);
}

Using condition variables for this kind of thing isn't the best idea. Semaphores are better suited to the task because those do have memory and remember their signaled state even if nobody is waiting on them when they are signaled.

于 2013-07-19T23:56:40.543 回答