【问题标题】:Race conditions in threads despite mutexlocking尽管有互斥锁,但线程中的竞争条件
【发布时间】:2019-10-12 02:00:19
【问题描述】:

此代码计算数组中所有整数的总和,在多个线程之间平均分配工作。然而,每隔一段时间,线程编号以及线程的本地总和就会被弄乱。我假设这是因为 void* param 和 globalindex 被多个线程同时访问。没有意义的是它发生的事实,即使我在这段代码中对每个全局变量都进行了互斥锁。 我该如何解决?

#include<string>
#include<iostream>
#include<fstream>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

using namespace std;
int y =0;
int sum=0;
int array[1000000];
int x=0;
int leftoverHandle = 0;
int globalindex = 0;  
int eachThreadHandles =0;

void* add(void* param){
    pthread_mutex_lock(&mutex);
    int localindexup = globalindex + eachThreadHandles;
    int localindexdown = globalindex;
    int localsum=0;
    long localparam = (long)param;

    if(y != leftoverHandle ){
            localindexup++;
            y++;

    }
    pthread_mutex_unlock(&mutex);


    while(localindexdown<localindexup){

            pthread_mutex_lock(&mutex);
            sum = sum+array[localindexdown];
            localsum = localsum+array[localindexdown];
            localindexdown++;
            pthread_mutex_unlock(&mutex);


    }




    pthread_mutex_lock(&mutex);
    globalindex = localindexdown;
    printf("Thread %ld", localparam);
    printf(": %d\n", localsum);
    pthread_mutex_unlock(&mutex);
}

int main(int argc, char ** argv){
    if(argc != 3){
            cout<<"Incorrect number of argument";
            exit(1);
    }
    string line;
    string f = argv[1];
    const char *filename = f.c_str();



    int maxthreads = atoi(argv[2]);

    FILE* inFile = fopen(filename,"r");
    int i=0;
    if(inFile == NULL){
    cout<<"fopen failed"<<endl;
    }

    fscanf(inFile, "%d",&i);

    while(!feof(inFile)){

    array[x]=i;
    x +=1;

    fscanf(inFile,"%d",&i);

    }

    fclose(inFile);

    pthread_t id[maxthreads];

    leftoverHandle = x%maxthreads;
    eachThreadHandles = (x - leftoverHandle)/maxthreads;


    for(long i=0; i< maxthreads;i++){
            long status = pthread_create(&id[i], NULL, add, (void*) i);
            if(status){
                    printf("Error creating thread! \n");
                    exit(0);
            }
    }

    for(long i=0; i<maxthreads;i++){
    pthread_join(id[i], NULL);
    }


    cout<<"Sum="<<sum<<endl;




return 0;
}

【问题讨论】:

    标签: c++ multithreading pthreads race-condition


    【解决方案1】:

    问题是您没有在每个线程初始化localindexuplocalindexdown 之后立即更新globalindex,即在第一个关键部分。
    您的代码中有三个关键部分。
    想象thread0 运行第一个临界区,然后thread1thread0 释放第一个临界区的锁之后抢占thread0。但是因为您在第三个临界区而不是第一个临界区将globalindex 设置为localindexdownthread1 仍然会看到globalindex=0,就像thread0 一样,所以它将重新计算与@ 相同的总和987654333@。您应该将globalindex = localindexdown; 放入第一个关键部分。
    实际上根本不需要第三个关键部分:

        pthread_mutex_lock(&mutex);
        int localindexup = globalindex + eachThreadHandles;
        int localindexdown = globalindex;
        int localsum=0;
        long localparam = (long)param;
    
        if(y != leftoverHandle ){
                localindexup++;
                y++;
    
        }
        globalindex = localindexdown; //<--- MOVED HERE
        pthread_mutex_unlock(&mutex);
    

    忘记我对循环的评论,我犯了一个错误:while(localindexdown&lt;localindexup) 可以安全地被抢占,因为变量不在线程之间共享。您可以通过减少互斥区域以仅包含共享数据来稍微提高性能:

        while(localindexdown<localindexup)
        {
                pthread_mutex_lock(&mutex);
                sum = sum+array[localindexdown];
                pthread_mutex_unlock(&mutex);     //<--- MOVED HERE
                localsum = localsum+array[localindexdown];
                localindexdown++;
        }
    

    【讨论】:

    • 不幸的是它没有解决我的问题。当我多次运行它时,仍然会出现竞争情况。这就是为什么我对它如此困惑。您的代码将每个变量都放入互斥锁中,但竞争条件仍然存在。
    • 你能用线程调用显示代码吗(你实际使用的那些add())?
    猜你喜欢
    • 2014-11-08
    • 2012-10-27
    • 1970-01-01
    • 2012-08-10
    • 2016-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    相关资源
    最近更新 更多