linux 多線程信號量(盤子水果問題)

  • 桌上有一空盤,允許存放一隻水果。爸爸可向盤中放蘋果,也可向盤中放桔子,兒子專等吃盤中的桔子,女兒專等吃盤中的蘋果。規定當盤空時一次只能放一隻水果供吃者取用,請用P、V原語實現爸爸、兒子、女兒三個併發進程的同步。
#include <stdlib.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <semaphore.h>

typedef struct{
    int     frt_tp;
    sem_t   sem_product;
    sem_t   sem_space;
    pthread_mutex_t mutex;
}frt_sem_mtx_def;


/*  父親線程:盤子中爲空,則隨機添加水果
    frt_tp值爲1-橘子,2-蘋果
    對frt_tp進行資源加鎖,更改後,釋放鎖
*/
void* fun_father(void* arg)
{
    frt_sem_mtx_def *frt = (frt_sem_mtx_def*)arg;
    int cnt = 0;
    while (1)
    {
        sem_wait(&frt->sem_space);
        sem_post(&frt->sem_product);

        sem_getvalue(&frt->sem_product, &cnt);
        pthread_mutex_lock(&frt->mutex);
        frt->frt_tp = rand()%2+1;
        pthread_mutex_unlock(&frt->mutex);
        printf("father Thread 0x%lx put %d fruit, count:%d\n", pthread_self(), frt->frt_tp, cnt);

        sleep(1);
    }
}

/*  兒子線程:加鎖訪問frt_tp值
    若值是1,則對盤子中水果減一,對盤子空間加一
    重置frt_tp爲0,最後釋放鎖
*/
void* fun_son(void* arg)
{
    frt_sem_mtx_def *frt = (frt_sem_mtx_def*)arg;

    int p_cnt = 0;
    int s_cnt = 0;
    
    while (1)
    {
        pthread_mutex_lock(&frt->mutex);
        if (frt->frt_tp == 1)
        {
            //對產品個數減一
            sem_wait(&frt->sem_product);
            //相應的空間加一
            sem_post(&frt->sem_space);
            sem_getvalue(&frt->sem_product, &p_cnt);
            sem_getvalue(&frt->sem_space, &s_cnt);

            printf("Son Thread 0x%lx take %d fruit, p_cnt:%d, s_cnt:%d\n", pthread_self(),frt->frt_tp, p_cnt, s_cnt);
            frt->frt_tp = 0;
        }
        pthread_mutex_unlock(&frt->mutex);
        sleep(1);
    }
    return (void*)0;
}

/*  女兒線程:加鎖訪問frt_tp值
    若值是2,則對盤子中水果減一,對盤子空間加一
    重置frt_tp爲0,最後釋放鎖
*/
void* fun_dau(void* arg)
{
    int p_cnt = 0;
    int s_cnt = 0;
    frt_sem_mtx_def *frt = (frt_sem_mtx_def*)arg;

    while (1)
    {
        pthread_mutex_lock(&frt->mutex);
        if (frt->frt_tp == 2)
        {
            //對產品個數減一
            sem_wait(&frt->sem_product);
            //相應的空間加一
            sem_post(&frt->sem_space);
            sem_getvalue(&frt->sem_product, &p_cnt);
            sem_getvalue(&frt->sem_space, &s_cnt);

            printf("dau Thread 0x%lx take %d fruit, p_cnt:%d, s_cnt:%d\n", pthread_self(), frt->frt_tp, p_cnt, s_cnt);
            frt->frt_tp = 0;
        }

        pthread_mutex_unlock(&frt->mutex);
        sleep(1);

    }

    return (void*)0;
}

int main()
{
    pthread_t id1, id2, id3;
    frt_sem_mtx_def frt;
    frt.frt_tp = 0;
    // 初始化信號量
    sem_init(&frt.sem_product, 0, 0); // 初始狀態水果爲0
    sem_init(&frt.sem_space, 0, 1);   // 空間設置一個
    pthread_mutex_init(&frt.mutex, NULL);

    pthread_create(&id1, NULL, fun_father, (void*)&frt);
    pthread_create(&id2, NULL, fun_son, (void*)&frt);
    pthread_create(&id3, NULL, fun_dau, (void*)&frt);

    pthread_join(id1, NULL);
    pthread_join(id2, NULL);
    pthread_join(id3, NULL);

    return 0;
}

運行結果如下:
father Thread 0xb75bfb40 put 2 fruit, count:1
dau Thread 0xb65bdb40 take 2 fruit, p_cnt:0, s_cnt:1
father Thread 0xb75bfb40 put 1 fruit, count:1
Son Thread 0xb6dbeb40 take 1 fruit, p_cnt:0, s_cnt:1
father Thread 0xb75bfb40 put 2 fruit, count:1
dau Thread 0xb65bdb40 take 2 fruit, p_cnt:0, s_cnt:1
father Thread 0xb75bfb40 put 2 fruit, count:1
dau Thread 0xb65bdb40 take 2 fruit, p_cnt:0, s_cnt:1
father Thread 0xb75bfb40 put 2 fruit, count:1
dau Thread 0xb65bdb40 take 2 fruit, p_cnt:0, s_cnt:1
father Thread 0xb75bfb40 put 2 fruit, count:1
dau Thread 0xb65bdb40 take 2 fruit, p_cnt:0, s_cnt:1
father Thread 0xb75bfb40 put 1 fruit, count:1
Son Thread 0xb6dbeb40 take 1 fruit, p_cnt:0, s_cnt:1
father Thread 0xb75bfb40 put 1 fruit, count:1
Son Thread 0xb6dbeb40 take 1 fruit, p_cnt:0, s_cnt:1
father Thread 0xb75bfb40 put 2 fruit, count:1
dau Thread 0xb65bdb40 take 2 fruit, p_cnt:0, s_cnt:1
father Thread 0xb75bfb40 put 2 fruit, count:1
dau Thread 0xb65bdb40 take 2 fruit, p_cnt:0, s_cnt:1

使用到信號量就可以達到這種效果,可以不需要使用到互斥鎖

#include <stdlib.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <semaphore.h>

typedef struct{
    int     frt_tp;
    sem_t   sem_product;
    sem_t   sem_space;
}frt_sem_mtx_def;


/*  父親線程:盤子中爲空,則隨機添加水果
    frt_tp值爲1-橘子,2-蘋果
    對frt_tp進行資源加鎖,更改後,釋放鎖
*/
void* fun_father(void* arg)
{
    frt_sem_mtx_def *frt = (frt_sem_mtx_def*)arg;
    while (1)
    {
        sem_wait(&frt->sem_space);
        frt->frt_tp = rand()%2+1;
        printf("father Thread 0x%lx put %d fruit\n", pthread_self(), frt->frt_tp);
        sem_post(&frt->sem_product);
        sleep(1);
    }
}

/*  兒子線程:加鎖訪問frt_tp值
    若值是1,則對盤子中水果減一,對盤子空間加一
    重置frt_tp爲0,最後釋放鎖
*/
void* fun_son(void* arg)
{
    frt_sem_mtx_def *frt = (frt_sem_mtx_def*)arg;

    int p_cnt = 0;
    int s_cnt = 0;
    
    while (1)
    {
        if (frt->frt_tp == 1)
        {
            //對產品個數減一
            sem_wait(&frt->sem_product);
            printf("Son Thread 0x%lx take %d fruit\n", pthread_self(),frt->frt_tp);
            frt->frt_tp = 0;
            //相應的空間加一
            sem_post(&frt->sem_space);
        }
        sleep(1);
    }
    return (void*)0;
}

/*  女兒線程:加鎖訪問frt_tp值
    若值是2,則對盤子中水果減一,對盤子空間加一
    重置frt_tp爲0,最後釋放鎖
*/
void* fun_dau(void* arg)
{
    int p_cnt = 0;
    int s_cnt = 0;
    frt_sem_mtx_def *frt = (frt_sem_mtx_def*)arg;

    while (1)
    {
        if (frt->frt_tp == 2)
        {
            //對產品個數減一
            sem_wait(&frt->sem_product);
            printf("dau Thread 0x%lx take %d fruit\n", pthread_self(), frt->frt_tp);
            frt->frt_tp = 0;
            //相應的空間加一
            sem_post(&frt->sem_space);
        }

        sleep(1);

    }

    return (void*)0;
}

int main()
{
    pthread_t id1, id2, id3;
    frt_sem_mtx_def frt;
    frt.frt_tp = 0;
    // 初始化信號量
    sem_init(&frt.sem_product, 0, 0); // 初始狀態水果爲0
    sem_init(&frt.sem_space, 0, 1);   // 空間設置一個

    pthread_create(&id1, NULL, fun_father, (void*)&frt);
    pthread_create(&id2, NULL, fun_son, (void*)&frt);
    pthread_create(&id3, NULL, fun_dau, (void*)&frt);

    pthread_join(id1, NULL);
    pthread_join(id2, NULL);
    pthread_join(id3, NULL);

    return 0;
}


father Thread 0xb7510b40 put 2 fruit
dau Thread 0xb650eb40 take 2 fruit
father Thread 0xb7510b40 put 1 fruit
Son Thread 0xb6d0fb40 take 1 fruit
father Thread 0xb7510b40 put 2 fruit
dau Thread 0xb650eb40 take 2 fruit
father Thread 0xb7510b40 put 2 fruit
dau Thread 0xb650eb40 take 2 fruit
father Thread 0xb7510b40 put 2 fruit
dau Thread 0xb650eb40 take 2 fruit
father Thread 0xb7510b40 put 2 fruit
dau Thread 0xb650eb40 take 2 fruit
father Thread 0xb7510b40 put 1 fruit
Son Thread 0xb6d0fb40 take 1 fruit
father Thread 0xb7510b40 put 1 fruit
Son Thread 0xb6d0fb40 take 1 fruit
father Thread 0xb7510b40 put 2 fruit
dau Thread 0xb650eb40 take 2 fruit
father Thread 0xb7510b40 put 2 fruit
dau Thread 0xb650eb40 take 2 fruit
father Thread 0xb7510b40 put 1 fruit
Son Thread 0xb6d0fb40 take 1 fruit

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章