- 爸爸放苹果,女儿吃苹果,必须有苹果才能吃(线程同步)
- 妈妈放梨子,儿子吃梨子,不许有梨子才能吃(线程同步)
- 果盘中最多能放20个水果,多了不能放
eatFruit.c
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include "type.h"
#include "eatFruit.h"
#include "output.h"
sem_t sem_remain, sem_apple, sem_pear, mutex;
EAT_FRUIT_S g_eat_fruit = {0};
FRUIT_NUM_S g_fruit_num = {0};
void sem_info_print()
{
int32 value = 0;
EAT_FRUIT_S *p_eat_info = &g_eat_fruit;
sem_getvalue(p_eat_info->p_sem_remain, &value);
DEBUG_OUTPUT("remain sem is %d\r\n", value);
sem_getvalue(p_eat_info->p_sem_apple, &value);
DEBUG_OUTPUT("apple sem is %d\r\n", value);
sem_getvalue(p_eat_info->p_sem_pear, &value);
DEBUG_OUTPUT("pear sem is %d\r\n", value);
sem_getvalue(p_eat_info->p_mutex, &value);
DEBUG_OUTPUT("mutex sem is %d\r\n", value);
}
EAT_FRUIT_S *get_eat_fruit_info()
{
return &g_eat_fruit;
}
FRUIT_NUM_S *get_fruit_num_info()
{
return &g_fruit_num;
}
uint32 eat_fruit_uninit()
{
sem_destroy(&sem_remain);
sem_destroy(&sem_apple);
sem_destroy(&sem_pear);
sem_destroy(&mutex);
}
uint32 eat_fruit_init()
{
EAT_FRUIT_S *p_eat_info = get_eat_fruit_info();
FRUIT_NUM_S *p_num_info = get_fruit_num_info();
p_num_info->remain = 20;
p_num_info->apple = 0;
p_num_info->pear = 0;
p_eat_info->p_sem_remain = &sem_remain;
p_eat_info->p_sem_apple = &sem_apple;
p_eat_info->p_sem_pear = &sem_pear;
p_eat_info->p_mutex = &mutex;
sem_init(&sem_remain, 0, p_num_info->remain);
sem_init(&sem_apple, 0, p_num_info->apple);
sem_init(&sem_pear, 0, p_num_info->pear);
sem_init(&mutex, 0, 1);
return 0;
}
void *father(void *p_para)
{
EAT_FRUIT_S *eat_info = NULL;
FRUIT_NUM_S *num_info = NULL;
DEBUG_OUTPUT("[father] function execute\r\n");
eat_info = get_eat_fruit_info();
while(1)
{
sem_wait(eat_info->p_sem_remain);
sem_wait(eat_info->p_mutex);
num_info = get_fruit_num_info(); /* critical resource must got in mutex */
DEBUG_OUTPUT("[father]Before place apple, remain = %u, apple = %u\r\n", num_info->remain--, num_info->apple++);
DEBUG_OUTPUT("[father]After place apple, remain = %u, apple = %u\r\n", num_info->remain, num_info->apple);
sem_post(eat_info->p_mutex);
sem_post(eat_info->p_sem_apple);
sleep(1);
}
}
void *mother(void *para)
{
EAT_FRUIT_S *eat_info = NULL;
FRUIT_NUM_S *num_info = NULL;
DEBUG_OUTPUT("[mother] function execute\r\n");
eat_info = get_eat_fruit_info();
while(1)
{
sem_wait(eat_info->p_sem_remain);
sem_wait(eat_info->p_mutex);
num_info = get_fruit_num_info(); /* critical resource must got in mutex */
DEBUG_OUTPUT("[mother]Before place pear, remain = %u, pear = %u\r\n", num_info->remain--, num_info->pear++);
DEBUG_OUTPUT("[mother]After place pear, remain = %u, pear = %u\r\n", num_info->remain, num_info->pear);
sem_post(eat_info->p_mutex);
sem_post(eat_info->p_sem_pear);
sleep(2);
}
}
void *son(void *para)
{
EAT_FRUIT_S *eat_info = NULL;
FRUIT_NUM_S *num_info = NULL;
DEBUG_OUTPUT("[son] function execute\r\n");
eat_info = get_eat_fruit_info();
while(1)
{
sem_wait(eat_info->p_sem_pear);
sem_wait(eat_info->p_mutex);
num_info = get_fruit_num_info(); /* critical resource must got in mutex */
DEBUG_OUTPUT("[son]Before eat pear, remain = %u, pear = %u\r\n", num_info->remain++, num_info->pear--);
DEBUG_OUTPUT("[son]After eat pear, remain = %u, pear = %u\r\n", num_info->remain, num_info->pear);
sem_post(eat_info->p_mutex);
sem_post(eat_info->p_sem_remain);
sleep(3);
}
}
void *daughter(void *p_para)
{
EAT_FRUIT_S *eat_info = NULL;
FRUIT_NUM_S *num_info = NULL;
DEBUG_OUTPUT("[daughter] function execute\r\n");
eat_info = get_eat_fruit_info();
while(1)
{
sem_wait(eat_info->p_sem_apple);
sem_wait(eat_info->p_mutex);
num_info = get_fruit_num_info(); /* critical resource must got in mutex */
DEBUG_OUTPUT("[daughter]Before eat apple, remain = %u, apple = %u\r\n", num_info->remain++, num_info->apple--);
DEBUG_OUTPUT("[daughter]After eat apple, remain = %u, apple = %u\r\n", num_info->remain, num_info->apple);
sem_post(eat_info->p_mutex);
sem_post(eat_info->p_sem_remain);
sleep(3);
}
}
int32 eat_fruit_create_thread(pthread_t *p_thread, void *func(void *), int8 *p_name)
{
int32 ret = 0;
ret = pthread_create(p_thread, NULL, func, NULL);
if (ret != 0)
{
DEBUG_OUTPUT("[main]%s pthread create failed\r\n", p_name);
return ret;
}
return ret;
}
int32 main(int32 argc, int8 *argv[])
{
int32 ret;
uint32 i;
pthread_t thread[4];
int8 *name[4] = {"father", "mother", "son", "daughter"};
CALLBACK_FUN call_back_func[4] = {father, mother, son, daughter};
// void *(*call_back_func[4])(void *) = {father, mother, son, daughter};
eat_fruit_init();
sem_info_print();
for (i = 0; i < 4; i++)
{
eat_fruit_create_thread(&thread[i], call_back_func[i], name[i]);
}
while(1)
{
;
}
return 0
}
eatFruit.h
#ifndef __EAT_FRUIT__
#define __EAT_FRUIT__
typedef void *(* CALLBACK_FUN)(void *);
typedef struct EatFruit
{
sem_t *p_sem_remain;
sem_t *p_sem_apple;
sem_t *p_sem_pear;
sem_t *p_mutex; /* used for access FRUIT_NUM_S */
}EAT_FRUIT_S;
typedef struct FruitNum
{
uint32 remain;
uint32 apple;
uint32 pear;
}FRUIT_NUM_S;
#endif
type.h
#ifndef __TYPE_H__
#define __TYPE_H__
typedef int int32;
typedef unsigned int uint32;
typedef char int8;
typedef unsigned char uint8;
#endif
output.h
#ifndef __OUTPUT_H__
#define __OUTPUT_H__
typedef int int32;
typedef unsigned int uint32;
typedef char int8;
typedef unsigned char uint8;
#endif
void debug_print(int8 *fmt, ...);
#define DEBUG_OUTPUT(fmt, ...) \
debug_print("(%s)"fmt, __TIME__, ##__VA_ARGS__);
#endif
output.c
#include <stdio.h>
#include <stdarg.h>
#include "type.h"
void debug_print(int8 *fmt, ...)
{
va_list arg;
int8 local_buf[100] = {0};
va_start(arg, fmt);
(void)vsprintf(local_buf, fmt, arg);
printf("%s\r\n", local_buf);
va_end(arg);
return;
}
makefile
CC=gcc
ROOT = /repo/ezheson/test_dm/eat_fruit
SRC_FILES = $(ROOT)/src/eatFruit.c \
$(ROOT)/src/output.c
OBJECTS=$(SRC_FILES:$(ROOT)/src/%.c=$(ROOT)/build/%.o) ## 替换src/*.c成build/*.o
INCLUDE:=-I$(ROOT)/inc
FLAGS=-lpthread
eatFruit.out:$(OBJECTS)
$(CC) $(FLAGS) $^ -o $@
$(OBJECTS):$(ROOT)/build/%.o:$(ROOT)/src/%.c
$(CC) $(INCLUDE) -c $< -o $@
.PHONY:clean
clean:
rm -rf *.out; cd build; rm -rf *.o
运行结果