linux 多线程信号量(盘子水果问题)

  • 桌上有一空盘,允许存放一只水果。爸爸可向盘中放苹果,也可向盘中放桔子,儿子专等吃盘中的桔子,女儿专等吃盘中的苹果。规定当盘空时一次只能放一只水果供吃者取用,请用P、V原语实现爸爸、儿子、女儿三个并发进程的同步。
#include 
#include 
#include 
#include 
#include 
#include 

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 
#include 
#include 
#include 
#include 
#include 

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

你可能感兴趣的:(linux,C,信号量,sem)