访问pthread共享标准:没有数据竞争的地图

时间:2015-09-07 18:43:47

标签: c++ multithreading locking pthreads

我的方案是拥有一个主线程和数十个工作线程。工作线程将处理来自不同端口的传入消息。

我想要做的是让主线程和工作线程共享一个相同的地图,工作线程将数据保存到地图中(在不同的存储桶中)。主线程定期grep地图内容。

代码如下:

struct cStruct
{
    std::map<string::string> map1; 
    pthread_mutex_t mutex1;
    pthread_mutex_t mutex2;  
};

int main(){

    struct cStruct cStruct1;   
    while (condition){
        pthread_t th;
        int th_rc=pthread_create(&th,NULL,&task,(void *) &cStruct1);
    }

}

void* task(void* arg){
    struct cStruct cs = * (struct cStruct*) arg;

    while (coming data){
        if (main_thread_work){
            pthread_cond_wait(&count_cond, &cs.mutex1)
        }  

        pthread_mutex_lock(&cs.mutex1);
        // add a new bucket to the map
        cs.map1(thread_identifier)=processed_value;
        pthread_mutex_unlock(&cs.mutex1);

    }

void* main_thread_task(void* arg){

    sleep(sleep_time);
    main_thread_work = true;
    pthread_mutex_lock(&cs.mutex1);
    // main_thread reads the std::map
    main_thread_work = false;
    pthread_cond_broadcast(&count_cond, &cs.mutex1)
    pthread_mutex_unlock(&cs.mutex1);    
}

我的问题是:

对于地图大小更改,我应该使用锁来保护地图。 但是对于具有某些密钥更新​​的地图,我可以让不同的线程同时修改地图吗? (假设不会同时访问两个相同的地图桶)

对于主线程greps地图,我想到使用条件等待来保存所有工作线程,而主线程正在掠过地图内容,然后做一个pthread_cond_broadcast来唤醒它。问题是,如果工作线程在主要开始工作时更新地图,则会有数据竞争。

请分享一些想法,以帮助我改进设计。

编辑1: 添加main_thread_task()。 我想避免的是工作线程到达pthread_cond_wait&#34;&#34; pthread_cond_broadcast并且逻辑出错。

所以我在主线程广播工作线程之前假为main_thread_work。

2 个答案:

答案 0 :(得分:0)

您应该在每次访问地图时使用mutex锁定机制(在您的情况下),而不仅仅是添加新的“#”桶。如果T1在T2插入新存储桶时尝试向映射写入某些值,则T1使用的指针/迭代器将变为无效。

关于pthread_cond_wait。如果其他线程做的唯一事情就是修改地图,它可以完成这项工作。如果他们执行其他计算或处理一些非共享数据,最好使用相同的mutex来保护对地图的访问,让其他线程完成他们的工作,这可能与共享地图无关。

答案 1 :(得分:0)

while (coming data){
    if (main_thread_work){
        pthread_cond_wait(&count_cond, &cs.mutex1)
    }  

    pthread_mutex_lock(&cs.mutex1);

这显然是不对的。除非您持有保护它的锁,否则无法检查main_thread_work。如何调用pthread_cond_wait释放它不存在的锁?!

这应该是这样的:

void* task(void* arg){
    struct cStruct cs = * (struct cStruct*) arg;

    // Acquire the lock so we can check shared state
    pthread_mutex_lock(&cs.mutex1);

    // Wait until the shared state is what we need it to be
    while (main_thread_work)
        pthread_cond_wait(&count_cond, &cs.mutex1)

    // Do whatever it is we're supposed to do when the
    // shared state is in this state
    cs.map1(thread_identifier)=processed_value;

    // release the lock
    pthread_mutex_unlock(&cs.mutex1);
}