使用互斥锁和条件变量调度多线程

时间:2015-03-26 11:02:02

标签: c multithreading synchronization mutex condition-variable

我正在尝试创建四个线程来打印一些消息 我正面临同步问题。

这是我的main()看起来像

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;    
pthread_cond_t  cond  = PTHREAD_COND_INITIALIZER; 
int count = 4;

int main (void)
{
    pthread_t thread1, thread2, thread3, thread4;
    pthread_create (&thread4, NULL, function4, NULL);
    pthread_create (&thread3, NULL, function3, NULL);
    pthread_create (&thread2, NULL, function2, NULL);
    pthread_create (&thread1, NULL, function1, NULL);

    pthread_join (thread1, NULL);
    pthread_join (thread2, NULL);
    pthread_join (thread3, NULL);
    pthread_join (thread4, NULL);
    return 0;                                                                   
}

function1()打印Function 1function2()打印Function 2,依此类推。

所需输出应如下:

Function 1   
Function 2  
Function 3  
Function 4

实际输出:

Function 1
/* Infinitely runs (Deadlock maybe) */

实际问题
我们可以使用一个单独的条件变量来同步两个或多个线程吗?如果是这样的话?

如果没有,我该如何解决这个问题?


以下是function(n)

的定义
void *function1 ()
{
    while (1)
    {
    if (count == 4)
        {
            pthread_mutex_lock (&mutex);
            printf("Function 1\n");
            count --;
            pthread_mutex_unlock (&mutex);
            pthread_cond_signal (&cond);
            return NULL;
        }
      else
          pthread_cond_wait(&cond, &mutex);
    }
    return NULL;
}

void *function2 ()
{
while (1)
    {
        if (count == 3)                                                         
        {
            pthread_mutex_lock (&mutex);
            printf("Function 2\n");
            count--;
            pthread_mutex_unlock (&mutex);
            pthread_cond_signal (&cond);                                        
            return NULL;
        }
        else                                                                    
            pthread_cond_wait(&cond, &mutex);        
    }
    return NULL;
}

void *function3 ()
{
    while (1)
    {
        if(count == 2)
        {
            pthread_mutex_lock (&mutex);
            printf("Function 3\n");
            count--;
            pthread_mutex_unlock (&mutex);
            pthread_cond_signal (&cond);
            return NULL;
        }
        else
            pthread_cond_wait(&cond, &mutex);      
    }
    return NULL;
}

void *function4 ()
{
    while (1)
    {
        if(count == 1)
        {
            pthread_mutex_lock (&mutex);
            printf("Function 4\n");
            pthread_mutex_unlock (&mutex);
            pthread_cond_signal (&cond);
            return NULL;
        }
        else
            pthread_cond_wait(&cond, &mutex);
    }
    return NULL;
}

2 个答案:

答案 0 :(得分:0)

所需的更改很简单:

而不是:

else
    pthread_cond_wait(&cond, &mutex);

这样做:

else {
    pthread_mutex_lock (&mutex);
    pthread_cond_wait(&cond, &mutex);
    pthread_mutex_unlock (&mutex);
}

这对我来说对这些变化很有用,但如果没有这些变化就会导致不可预测的行为。

编辑:

上述简单方法仍然存在竞争条件,并且无法修复signal vs broadcast问题。为避免这种情况,代码的结构应如下所示:

pthread_mutex_lock (&mutex);
if (count == 4)
{
    printf("Function 1\n");
    count --;
    pthread_mutex_unlock (&mutex);
    pthread_cond_broadcast (&cond); // NOTE: broadcast, not signal!
    return NULL;
 }
else
    pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock (&mutex);

请注意,pthread_cond_broadcast是必要的,因为您要唤醒所有线程。

答案 1 :(得分:0)

经过更清楚的理解,我已经解决了这个问题 这是种族情况。

代码有问题:

  1. 使用pthread_cond_broadcast代替pthread_cond_signal 来自man页面

      

    pthread_cond_broadcast()函数将取消阻止当前在指定条件变量cond上阻塞的所有线程。

         

    pthread_cond_signal()函数将取消阻止至少一个在指定条件变量cond上被阻塞的线程

  2. 在检查lock之前未获取if (count == X),需要a     在此之前放置一个锁(因为count是全局/共享变量)。

  3. 如果控件转到unlock,则不会放置else。自从锁定 已放置(else之前),您需要unlock 它。

    如果你没有这样做,其他线程会尝试lock互斥, 已经锁定,导致竞争条件。

  4. 功能应如下

    void *function1 ()
    {
        while (1)
        {
            /* Take a lock on the Mutex */
            pthread_mutex_lock (&mutex);
            if (4 == count)
            {
                printf("Function 1\n");    /* Perform your task */
                count--;
                /* Once operation on shared variable (count) is completed, release lock*/
                pthread_mutex_unlock (&mutex);
    
                /* Broadcast to other threads about completion of task */
                pthread_cond_broadcast (&cond);
                return NULL;
            }
            else 
            { 
                /* If count doesnt match, wait on the condition (wait for signal from other threads) */
                pthread_cond_wait(&cond, &mutex);   
                /* Unlock the mutex, since it was locked earlier - else goes to deadlock */
                pthread_mutex_unlock (&mutex);
            }
        }
        return NULL;
    }
    

    Here是完整的工作代码。