簡體   English   中英

Pthreads-具有條件變量和互斥量的生產者和使用者-連接錯誤和奇怪的cout

[英]Pthreads - Producer and consumer with condition variable and mutex - join error and strange cout

我正在使用pthreads編寫多線程程序。 這個想法很簡單:

  • 汽車(螺紋)
  • 汽油供應(螺紋)
  • 加油站(資源)

汽車和加油站都具有一定的燃料容量,汽車用完燃料后需要前往加油站。 加油站用完燃料后,加油口運行並重新加油。 一切似乎是罰款不包括我不得不使用pthread_exit ,而不是pthread_join等待中的主要功能,有時雙線程cout為同一輛車出現: "-----End of fuel-----" 我做對了嗎?

結構和一些全局變量:

#define initialFuel 100
#define loop 10

pthread_mutex_t mutex1, mutex2;
pthread_cond_t isempty;
PetrolDistributor petrolDistributor;

struct Car {
    int capacity = 10;
    int petrol = 5;
};

struct PetrolDistributor {
    int petrol = initialFuel;
    bool isEmpty = false;
};

線程數:

void * threadSupply(void *arg )
{
    for(int i = 0; i<loop; i++) 
{
        pthread_mutex_lock(&mutex1);

        while(!petrolDistributor.isEmpty)
        {
            pthread_cond_wait(&isempty, &mutex1);   //When signal received, do below:
            usleep(2000000);
            petrolDistributor.petrol = initialFuel; //Refill petrol and change state
            petrolDistributor.isEmpty = false;
        }
        pthread_mutex_unlock(&mutex1);
    }
}

void * threadPetrolDriver(void *arg )
{
    Car *car;
    car = (Car*) arg;

    for(int i = 0; i<loop; i++) 
    {
        while(car->petrol > 0) // Car consumes petrol here
        {
            usleep(200000);
            cout << car->petrol << endl;
            car->petrol -= 1;
        }
        cout << "-----End of fuel-----" << "\t\t #" << i << endl;

        pthread_mutex_lock(&mutex1);
        if (petrolDistributor.petrol >= 30)  // If distributor almost empty?
        {
            petrolDistributor.petrol -= car->capacity;  //Substract car's capacity amount of fuel from distributor
            car->petrol = car->capacity;               //Fillup mentioned capacity in car
        }
        else
        {
            petrolDistributor.isEmpty = true;
            pthread_cond_signal(&isempty);
        }
        pthread_mutex_unlock(&mutex1);
    }
}

主要:

int main()
{    
    pthread_t car;
    pthread_t supply;

    Car carPetrol;

    pthread_cond_init(&isempty, NULL);
    pthread_mutex_init(&mutex1, NULL);

    pthread_create(&car, NULL, threadPetrolDriver, (void*) (&carPetrol));
    pthread_create(&supply, NULL, threadSupply, NULL);

   // pthread_join(&car, NULL);     //results error: invalid conversion from ‘pthread_t* {aka long unsigned int*}’ to ‘pthread_t {aka long unsigned int}’ [-fpermissive]|
   // pthread_join(&supply, NULL);
    pthread_exit(NULL);

    return 0;
}

輸出示例:

-----End of fuel-----    #0
9
(...)
2
1
-----End of fuel-----    #1
-----End of fuel-----    #2  //Also for loop increments
10
9
(...)
3
2
1
-----End of fuel-----    #3
10
9
(...)

問題是為什么輸出看起來像這樣? 有時可以進行五次迭代,而第六次則顯示兩次消息。 加入有什么問題? 感謝您的建議。

這輛車可以多次顯示“燃料用盡”,因為如果發現petrolDistributor快要空了,它就不會等待-它再次在while循環外旋轉,而無需加油。

如果它發現petrolDistributor的燃料不足以供汽車加油,那么您應該在這里讓汽車等待條件變量。 在petrolDistributor加油之前,不應進行以下操作:

pthread_mutex_lock(&mutex1);
if (petrolDistributor.petrol < 30)  // If distributor almost empty?
    pthread_cond_signal(&isempty);

// wait for sufficient fuel to be available
while (petrolDistributor.petrol < car->capacity)
    pthread_cond_wait(&carwaiting, &mutex1);

// refuel
petrolDistributor.petrol -= car->capacity;  //Substract car's capacity amount of fuel from distributor
car->petrol = car->capacity;               //Fillup mentioned capacity in car
pthread_mutex_unlock(&mutex1);

我用了一個新的變量conditiona carwaiting這里。 請注意,不需要petrolDistributor.isEmpty布爾值-該謂詞只是petrolDistributor.petrol < 30

petrolDistributor在加油站加油后需要發信號通知正在等待的汽車:

    pthread_mutex_lock(&mutex1);

    // Wait for petrol to drop below low-water-mark
    while(petrolDistributor.petrol >= 30)
        pthread_cond_wait(&isempty, &mutex1);

    usleep(2000000);
    petrolDistributor.petrol = initialFuel; //Refill petrol and change state
    pthread_cond_broadcast(&carwaiting); // Wake up any cars waiting for fuel
    pthread_mutex_unlock(&mutex1);

注意,我在這里使用了pthread_cond_broadcast() ,因為如果將其擴展為包括多輛汽車,則可能有多個汽車在等待加油。

您的pthread_join()調用應該只是:

pthread_join(car, NULL);
pthread_join(supply, NULL);

pthread_join()pthread_t作為參數,而不是pthread_t * )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM