c中的多线程互斥

时间:2014-07-21 08:05:46

标签: c linux multithreading mutex

我的代码执行以下操作:创建N个线程,每个线程将全局变量计数器增加M次。我使用互斥锁以确保计数器的最终值是M * N.

我想观察没有互斥的情况,为计数器获取不同的值,以便正确评估互斥锁的工作。我注释掉了互斥锁,但结果是一样的。我应该让他们在一段时间内睡觉吗?我该怎么办?

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

#define N 10
#define M 4

pthread_mutex_t mutex;
int counter=0;

void *thread_routine(void *parameter)
{
    pthread_mutex_lock(&mutex);
    int i;
    for (i=0; i<M; i++)
        counter++;
    pthread_mutex_unlock(&mutex);
}

int main(void)
{
    pthread_t v[N];
    int i;

    pthread_mutex_init(&mutex,NULL);

    for (i=0; i<N; i++)
    {
        pthread_create(&v[i],NULL,thread_routine,NULL);
    }

    for (i=0; i<N; i++)
    {
        pthread_join(v[i],NULL);
    }

    printf("%d %d\n",counter,N*M);
    if (N*M==counter)
        printf("Success!\n");
    pthread_mutex_destroy(&mutex);

    return 0;
}

1 个答案:

答案 0 :(得分:4)

我不知道你使用了什么编译器,但在这种情况下g ++会完全消除线程并在编译时计算计数器的最终值。 为了防止这种优化,你可以使计数器变量不稳定

volatile int counter=0;

由于这将告诉编译器变量可以随时由外部资源更改,因此不得对可能有副作用的变量进行任何优化。由于外部资源可能会更改该值,因此最终值可能不是N * M的结果,因此计数器的值将在运行时计算。 WhozCraig在他的评论中所说的内容也很可能适用于您的案例。但我认为他的意思是M,而不是N.

除了你原来的问题:当你连接所有线程时读取计数器,可能值得为每个线程提供自己的计数器,并在完成计算时对所有线程的计数器求和。这样,您可以在没有任何锁定或原子操作的情况下计算最终值。

编辑:

您使用互斥锁的第一次测试看起来像这样

#define N 10
#define M 10000000

pthread_mutex_t mutex;
volatile int counter=0;

void *thread_routine(void *parameter)
{
    pthread_mutex_lock(&mutex);
    int i;
    for (i=0; i<M; i++)
        counter++;
    pthread_mutex_unlock(&mutex);
}

和你没有互斥的第二次测试

#define N 10
#define M 10000000

pthread_mutex_t mutex;
volatile int counter=0;

void *thread_routine(void *parameter)
{
//  pthread_mutex_lock(&mutex);
    int i;
    for (i=0; i<M; i++)
        counter++;
//  pthread_mutex_unlock(&mutex);
}

而第二次测试在递增计数器变量时将具有预期的竞争条件。

编译可以使用gcc -O3 -lpthread test.c

完成