- 桌上有一空盤,允許存放一隻水果。爸爸可向盤中放蘋果,也可向盤中放桔子,兒子專等吃盤中的桔子,女兒專等吃盤中的蘋果。規定當盤空時一次只能放一隻水果供吃者取用,請用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