使用线程时如何避免全局信号量和队列

时间:2018-11-02 19:59:26

标签: c++ multithreading concurrency

我的代码有问题。它有效,但是我无法避免使用全局信号量。我有3个线程功能。第一个由10个线程运行。第二个和第三个分别由2个线程运行。这些线程应在没有竞争条件的情况下运行。另外,他们应该互相沟通。我使用用户定义的队列类在线程之间以及线程和main之间进行通信。另外,我使用信号量实现线程之间的互斥。由于我以全局方式声明了队列类和信号量的实例,因此我不必将它们传递给任何函数。这些程序中的任何功能都可以访问它们。但是,这不是编写程序的健康方法。因此,我问你,如何在本地声明队列和信号量,以及在线程之间传递它们的最佳方法是什么。

// queueString标头

#include <string>
#include <queue>
#include <semaphore.h>

using namespace std;

class queueString
{
public:
    queueString();
    ~queueString();
    void qPush(string str);
    string qPop();
private:
    sem_t queueSem;
    queue <string> q;
};

// queueString类

#include "queueString.h"

using namespace std;

// queue class that will enqueue and dequeue atomically.
queueString::queueString(){
    sem_init(&queueSem, 0, 1);
}
queueString::~queueString(){}

void queueString::qPush(string str){
    sem_wait(&queueSem);
    this->q.push(str);
    sem_post(&queueSem);
}

string queueString::qPop(){
    sem_wait(&queueSem);
    string str = this->q.front();
    q.pop();
    sem_post(&queueSem);
    return str;
}

//具有主线程的三个线程

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
#include "queueString.h"

using namespace std;

//My question is here, How to declare the variables below locally, and where 
// is the right place to declare them, and how to pass them to threads?

sem_t s12, s13, s21, s31, sthr1, sthr2[2], sthr3[2], printSem;
sem_t idInitializationSemMainToThread, idInitializationSemThreadToMain;
queueString q = queueString();

#define THR1NUM 10
#define THR2NUM 2
#define THR3NUM 2

void printString(string str);

void *thread1(void* arg){
    sem_wait(&idInitializationSemMainToThread);
    int *pnum = (int *)arg;
    int thr_1_ID = *pnum;
    sem_post(&idInitializationSemThreadToMain);
    sem_wait(&sthr1);
    string value= "THR1 ";
    value.append(to_string(thr_1_ID));
    q.qPush(value);
    sem_post(&s12);
    sem_wait(&s21);
    value= "2nd Iteration THR1 ";
    value.append(to_string(thr_1_ID));
    q.qPush(value);
    sem_post(&s13);
    sem_wait(&s31);
    sem_post(&sthr1);

}

void *thread2(void* arg){
    sem_wait(&idInitializationSemMainToThread);
    int *pnum = (int *)arg;
    int thr_2_ID = *pnum;
    sem_post(&idInitializationSemThreadToMain);
    while (true)
    {
        sem_wait(&sthr2[thr_2_ID]);
        sem_wait(&s12);
        string readVal = q.qPop();
        printString(readVal + ", THR2 "+ to_string(thr_2_ID));

        if (thr_2_ID==0)
            sem_post(&sthr2[1]); 
        else
            sem_post(&sthr2[0]); 
        sem_post(&s21);
    }
}

void *thread3(void* arg){
    sem_wait(&idInitializationSemMainToThread);
    int *pnum = (int *)arg;
    int thr_3_ID = *pnum;
    sem_post(&idInitializationSemThreadToMain);

    while (true)
    {
        sem_wait(&sthr3[thr_3_ID]);
        sem_wait(&s13);
        string readVal = q.qPop();
        printString(readVal + " THR3 " + to_string(thr_3_ID));
        if (thr_3_ID == 0)
             sem_post(&sthr3[1]);
        else
            sem_post(&sthr3[0]);  

        sem_post(&s31);
    }
}

int main(){
    pthread_t thr1[THR1NUM], thr2[THR2NUM], thr3[THR3NUM];

    sem_init(&s12, 0, 0);
    sem_init(&s13, 0, 0);
    sem_init(&s31, 0, 0);
    sem_init(&s21, 0, 0);
    sem_init(&printSem, 0, 1);
    sem_init(&sthr1, 0, 0);
    for (int i = 0; i < 2;i++)
        sem_init(&sthr2[i], 0, 0);
    for (int i = 0; i < 2;i++)
        sem_init(&sthr3[i], 0, 0);
    sem_init(&idInitializationSemMainToThread, 0, 0);
    sem_init(&idInitializationSemThreadToMain, 0, 0);

    int *pnum =(int *) malloc(sizeof(int));

    for (int j = 0; j < THR2NUM;j++){
        *pnum = j;
        pthread_create(&thr2[j], NULL, thread2, (void *)pnum);
        sem_post(&idInitializationSemMainToThread);
         printString("thr2 "+to_string(j)+ " created");
        sem_wait(&idInitializationSemThreadToMain);
    }
    for (int k = 0; k < THR3NUM;k++){
        *pnum = k;
        pthread_create(&thr3[k], NULL, thread3,(void *) pnum);
        sem_post(&idInitializationSemMainToThread);
        printString("thr3 "+to_string(k)+ " created");
        sem_wait(&idInitializationSemThreadToMain);
    }
    for (int i = 0; i < THR1NUM;i++){
        *pnum = i;
        pthread_create(&thr1[i], NULL, thread1,(void *) pnum);
        sem_post(&idInitializationSemMainToThread);
        printString("thr1 "+to_string(i)+ " created");
        sem_wait(&idInitializationSemThreadToMain);
    }
    sem_post(&sthr2[0]);
    sem_post(&sthr3[0]);
    sem_post(&sthr1);

    for (int i = 0; i < THR1NUM;i++){
        pthread_join(thr1[i], NULL);
        printString("thr1 "+to_string(i)+ " joined");
    }

    for (int i = 0; i < THR2NUM; i++){
        pthread_cancel(thr2[i]);
        printString("thr2 "+to_string(i)+ " exited");
    }
    for (int i = 0; i < THR3NUM;i++){
        pthread_cancel(thr3[i]);
        printString("thr3 "+to_string(i)+ " exited");
        sem_post(&printSem);
    }



    sem_destroy(&s12);
    sem_destroy(&s21);
    sem_destroy(&s13);
    sem_destroy(&s31);
    sem_destroy(&sthr1);

    free(pnum);
}

// function to print strings atomically.
void printString(string str){
    sem_wait(&printSem);
    printf("%s\n", str.c_str());
    sem_post(&printSem);
}

0 个答案:

没有答案