是否有另一种同步方式

时间:2017-03-22 13:24:03

标签: multithreading thread-safety pthreads thread-synchronization

是否有另一种方法可以确保线程已准备好接收广播信号。我想替换main中的Sleep(1)函数。

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

#define NUM 4


using namespace std;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_t tid[NUM];


void *threads(void *arg){
    int tid = (int)arg;
    while(true){
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond,&mutex);
        //do some work
        cout<<"Thread: "<<tid<<endl;;
        pthread_mutex_unlock(&mutex);
    }
}

int main(){

    for(int i=0;i<NUM;i++){
        pthread_create(&tid[i],NULL,threads,(void*)i);
    }

    Sleep(1);
    pthread_cond_broadcast(&cond);

    Sleep(1);
    pthread_cond_broadcast(&cond);

    Sleep(1);
    pthread_cond_broadcast(&cond);

    return 0;
}

我在pthread_cond_wait之前尝试了内存屏障,我想使用计数器,但是对我来说没有任何作用。

1 个答案:

答案 0 :(得分:0)

条件变量通常连接到谓词。在其他线程中,检查谓词是否已经满足(在保持谓词的互斥锁的同时检查),如果是,则不要等待条件变量。主要是,获取互斥锁,在持有互斥锁的同时更改谓词。然后在condvar上释放互斥锁并发出信号或广播。这是一个类似的问题: Synchronisation before pthread_cond_broadcast

以下是一些示例代码:

#include <iostream>
#include <pthread.h>
#include <unistd.h>

#include <cassert>

#define NUM 4
#define SIZE 256


using std::cout;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_t tid[NUM];

int work_available;

void *threads(void *arg)
{
    int tid = *((int*)arg);
    while (1) {
        pthread_mutex_lock(&mutex);
        while (work_available == 0) {
            // While loop since cond_wait can have spurious wakeups.                                                                                                                                                                                                                                                                                                                        
            pthread_cond_wait(&cond, &mutex);
            cout << "Worker " << tid << " woke up...\n";
            cout << "Work available: " << work_available << '\n';
        }
        if (work_available == -1) {
            cout << "Worker " << tid << " quitting\n";
            pthread_mutex_unlock(&mutex); // Easy to forget, better to use C++11 RAII mutexes.                                                                                                                                                                                                                                                                                              
            break;
        }
        assert(work_available > 0);
        work_available--;
        cout << "Worker " << tid << " took one item of work\n";
        pthread_mutex_unlock(&mutex);

        //do some work                                                                                                                                                                                                                                                                                                                                                                      
        sleep(2); // simulated work                                                                                                                                                                                                                                                                                                                                                         
        pthread_mutex_lock(&mutex);
        cout << "Worker " << tid << " done with one item of work.\n";
        pthread_mutex_unlock(&mutex);
    }
}


int main()
{
    work_available = 0;

    int args[NUM];
    for (int i=0; i<NUM; i++) {
        args[i] = i;
        pthread_create(&tid[i], NULL, threads, (void*)&args[i]);
    }

    const int MAX_TIME = 10;
    for (int i = 0; i < MAX_TIME; i++)
    {
        pthread_mutex_lock(&mutex);
        work_available++;
        cout << "Main thread, work available: " << work_available << '\n';
        pthread_mutex_unlock(&mutex);
        pthread_cond_broadcast(&cond);
        sleep(1);
    }

    pthread_mutex_lock(&mutex);
    cout << "Main signalling threads to quit\n";
    work_available = -1;
    pthread_mutex_unlock(&mutex);
    pthread_cond_broadcast(&cond);

    for (int i = 0; i < NUM; i++)
    {
        pthread_join(tid[i], NULL);

    }
    return 0;
}