原文网址https://blog.csdn.net/life_hunter/article/details/8790553,本文是对原文的说明
1.生产者-消费者问题
1) sem.c 实现了生产者和消费者的同步。
当生产者多于消费者的时候,产品最多可以达到8个。不会冒。
当消费者多于生产者的时候,产品最少不会少于0个,不会负值。
实现同步。注意这个例子是total_num从3减到1,才开始加的,1+7=8.所以最多到8.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
#define msleep(x) usleep(x*1000)
#define PRODUCT_SPEED 3
#define CONSUM_SPEED 1
#define INIT_NUM 3
#define TOTAL_NUM 10
sem_t p_sem,c_sem,sh_sem;
int num=INIT_NUM;
void product (void)
{
sleep (PRODUCT_SPEED);
}
int add_to_lib ()
{
num++;
msleep(500);
return num;
}
void consum()
{
sleep(CONSUM_SPEED);
}
int sub_from_lib ()
{
num--;
msleep(500);
return num;
}
void *productor(void *arg)
{
while (1)
{
sem_wait(&p_sem);
product();
sem_wait(&sh_sem);
printf("push into!total_num=%d\n",add_to_lib());
sem_post(&sh_sem);
sem_post(&c_sem);
}
}
void *consumer (void *arg)
{
while (1)
{
sem_wait(&c_sem);
sem_wait(&sh_sem);
printf("pop out!total_num=%d\n",sub_from_lib());
sem_post(&sh_sem);
sem_post(&p_sem);
consum();
}
}
int main ()
{
pthread_t tid1,tid2, tid3,tid4;
//10-3=7
sem_init(&p_sem,0,TOTAL_NUM-INIT_NUM);
//3
sem_init(&c_sem,0,INIT_NUM);
sem_init(&sh_sem,0,1);
pthread_create(&tid1,NULL,productor,NULL);
pthread_create(&tid3,NULL,productor,NULL);
pthread_create(&tid4,NULL,productor,NULL);
pthread_create(&tid2,NULL,consumer,NULL);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 0;
}
2) sem1.c和sem.c一样。
只是将同步的 sem_wait(&sh_sem);换成了pthread_mutex_lock(&mutex);
注意:其empty init is 5
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
#define N 2
#define N1 3
#define N2 1
#define M 10
int in =0 ;
int out =0 ;
int buff[M]={0};
sem_t empty_sem;
sem_t full_sem;
pthread_mutex_t mutex;
int product_id = 0;
int prochase_id = 0;
void print()
{
int i;
for (i=0;i<M;i++)
printf("%d",buff[i]);
printf("\n");
}
void *product()
{
int id= ++product_id;
while (1)
{
sleep (1);
sem_wait(&empty_sem);
pthread_mutex_lock(&mutex);
in = in %M;
printf("product %d in %d.like:\t",id,in);
buff[in]=1;
print();
++in;
pthread_mutex_unlock(&mutex);
sem_post(&full_sem);
}
}
void *prochase ()
{
int id=++prochase_id;
while(1)
{
sleep(1);
sem_wait(&full_sem);
pthread_mutex_lock(&mutex);
out = out % M;
printf("prochase %d in %d.like: \t",id,out);
buff[out]=0;
print();
++out;
pthread_mutex_unlock(&mutex);
sem_post(&empty_sem);
}
}
int main ()
{
pthread_t id1[10];
pthread_t id2[10];
int i;
int ret[10];
int ini1=sem_init(&empty_sem,0,M-5);
int ini2=sem_init(&full_sem,0,0);
if (ini1 && ini2 !=0)
{
printf("sem init failed\n");
exit(1);
}
int ini3=pthread_mutex_init(&mutex,NULL);
if (ini3!=0)
{
printf("mutex init failed \n");
exit (1);
}
for (i=0;i<N1;i++)
{
ret[i]=pthread_create(&id1[i],NULL,product,NULL);
if (ret[i]!=0)
{
printf("product %d creation failed\n",i);
exit(1);
}
}
for (i=0;i<N2;i++)
{
ret[i]=pthread_create(&id2[i],NULL,prochase,NULL);
if (ret[i]!=0)
{
printf("prochase %d creation failed\n",i);
exit(1);
}
}
for ( i=0;i<N;i++)
{
pthread_join(id1[i],NULL);
pthread_join(id2[i],NULL);
}
exit(0);
}
3) [cpp] view plaincopy
- /*===============================================================
- * File Name : producerConsumerProblem.c
- * Creation Date : 2013-04-11
- * Last Modified : 2013年04月11日 星期四 20时53分13秒
- * Purpose :test linux semaphore usage
- ================================================================*/
- #include <stdio.h>
- #include <sys/types.h>
- #include <semaphore.h>
- #include <pthread.h>
- #include <stdlib.h>
- void *producer_handler(void *ptr);
- void *consumer_handler(void *ptr);
- sem_t mutex,blank,fill;
- int *buffer;
- int in=0,out=0,buffer_size=10;
- void main()
- {
- if((buffer=(int *)malloc(buffer_size*sizeof(int)))==NULL)
- printf("can't allocate memroy on heap\n");
- sem_init(&mutex,0,1);
- sem_init(&blank,0,buffer_size);
- sem_init(&fill,0,0);
- int err;
- pthread_t producer,consumer;
- err=pthread_create(&producer,NULL,producer_handler,NULL);
- if(err!=0)
- err_quit("can't create thread: %s\n",strerror(err));
- err=pthread_create(&consumer,NULL,consumer_handler,NULL);
- if(err!=0)
- err_quit("can't create thread: %s\n",strerror(err));
- sleep(10);
- }
- void *producer_handler(void *ptr)
- {
- while(1){
- static int data=0;
- sem_wait(&blank);
- // sem_wait(&mutex);
- buffer[in]=++data;
- printf("%d has been input to the buffer\n",data);
- in=(in+1+buffer_size)%buffer_size;
- // sem_post(&mutex);
- sem_post(&fill);
- sleep(1);
- }
- return ((void *)0);
- }
- void *consumer_handler(void *ptr)
- {
- while(1){
- int fetch;
- sem_wait(&fill);
- // sem_wait(&mutex);
- fetch=buffer[out];
- out=(out+1+buffer_size)%buffer_size;
- printf("%d has been fetched\n",fetch);
- // sem_post(&mutex);
- sem_post(&blank);
- sleep(2);
- }
- return ((void *)0);
- }
2.读者-写者问题
1) 题目大意如下:有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者读时写者也不能写。
当有读者的时候,readCount!=0,所以不能写。
当写的时候。readCount==0,同时pthread_mutex_lock(&wr);
所以无法读,因为第一个读者,要检测是不是在写。
每个读,局部变量,控制每个读的结束。
实现了读写同步,读读并行。
#include <pthread.h>
#include <signal.h>
#define N 5
#define M 10
pthread_mutex_t rd = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t wr = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t priority = PTHREAD_MUTEX_INITIALIZER;
int readCount = 0;
void* reader(void *arg)
{
int n = M;
int id = (int)arg;
while (n--)
{
sleep(rand()%3);
pthread_mutex_lock(&priority);
pthread_mutex_lock(&rd);
readCount++;
if ( readCount ==1)
{
pthread_mutex_lock(&wr);
}
pthread_mutex_unlock(&rd);
pthread_mutex_unlock(&priority);
printf("reader %d is reading \n",id);
sleep(rand()%3);
pthread_mutex_lock(&rd);
readCount--;
if (readCount==0)
{
pthread_mutex_unlock(&wr);
}
pthread_mutex_unlock(&rd);
printf("reader %d is leaving \n",id);
}
printf("----reader %d has done----\n",(int)arg);
}
void* writer(void *arg)
{
int n = M;
while (n--)
{
sleep (rand()%4);
pthread_mutex_lock(&priority);
pthread_mutex_lock(&wr);
printf("\twriter is writing \n");
sleep (rand()%4);
pthread_mutex_unlock(&priority);
pthread_mutex_unlock(&wr);
printf("\twriter is leaving \n");
}
printf("----writer has done ----\n");
}
int main (int argc ,const char *asrgv[])
{
int err;
pthread_t tid[N],writer_tid;
int i;
for (i=0;i<N;i++)
{
err=pthread_create(&tid[i],NULL,reader,(void *)(i+1));
if (err !=0) {
printf("can;t create process for reader");
}
}
err = pthread_create(&writer_tid,NULL,writer,(void *)NULL);
if (err!=0)
{
printf("can;t cretee process for writer\n");
}
pause ();
return 0;
}
2)
- /*===============================================================
- * File Name : readerWriterProblem.c
- * Creation Date : 2013-04-11
- * Last Modified : 2013年04月11日 星期四 22时42分45秒
- * Purpose :
- ================================================================*/
- #include <stdio.h>
- #include <sys/types.h>
- #include <semaphore.h>
- #include <pthread.h>
- #include <stdlib.h>
- #define READER_NUM 5
- void *reader_handler(void *ptr);
- void *writer_handler(void *ptr);
- sem_t write_mutex;
- sem_t mutex;
- int read_count;
- void main()
- {
- sem_init(&write_mutex,0,1);
- sem_init(&mutex,0,1);
- read_count=0;
- int err,i;
- pthread_t reader[READER_NUM],writer;
- int args[READER_NUM];
- for(i=0;i<READER_NUM;++i){
- args[i]=i;
- err=pthread_create(&reader[i],NULL,reader_handler,(void*)&args[i]);
- if(err!=0)
- err_quit("can't create thread: %s\n",strerror(err));
- }
- err=pthread_create(&writer,NULL,writer_handler,NULL);
- if(err!=0)
- err_quit("can't create thread: %s\n",strerror(err));
- sleep(10);
- }
- void *reader_handler(void *ptr)
- {
- while(1){
- if(read_count==0){
- sem_wait(&write_mutex);
- }
- sem_wait(&mutex);
- ++read_count;
- sem_post(&mutex);
- printf("There are %d readers reading\n",read_count);
- sleep(1);
- sem_wait(&mutex);
- --read_count;
- sem_post(&mutex);
- if(read_count==0){
- sem_post(&write_mutex);
- }
- sleep(1);
- }
- return ((void *)0);
- }
- void *writer_handler(void *ptr)
- {
- while(1){
- if(read_count==0){
- sem_wait(&write_mutex);
- printf("Writer writes\n");
- sem_post(&write_mutex);
- }
- else
- printf("Writer failed\n");
- sleep(1);
- }
- return ((void *)0);
- }
3.哲学家进餐问题
有一点要注意: 就是循环生生成线程时,要给线程处理函数传入计数器参数时,不能直接用计数器的地址——因为计数器会现在主函数中改变。显然也不能用循环中的临时变量来记录。所以只好再有外部数组来记录这些实参值了。
- /*===============================================================
- * File Name : dinningPhilosophersProblem.c
- * Creation Date : 2013-04-11
- * Last Modified : 2013年04月11日 星期四 21时34分18秒
- * Purpose :
- ================================================================*/
- #include <stdio.h>
- #include <sys/types.h>
- #include <semaphore.h>
- #include <pthread.h>
- #include <stdlib.h>
- #define PHILO_NUM 5
- void *philosopher(void *arg);
- sem_t sema[PHILO_NUM];
- sem_t mutex;
- void main()
- {
- int i,err;
- int args[PHILO_NUM];
- for(i=0;i<PHILO_NUM;++i){
- sem_init(sema+i,0,1);
- args[i]=i;
- }
- sem_init(&mutex,0,1);
- pthread_t philosophers[PHILO_NUM];
- for(i=0;i<PHILO_NUM;++i){
- err=pthread_create(philosophers+i,NULL,philosopher,(void*)&args[i]);
- if(err!=0)
- err_quit("can't create thread: %s\n",strerror(err));
- }
- sleep(5);
- }
- void *philosopher(void *arg)
- {
- int num;
- num=*((int *)arg);
- //printf("Philosopher %d eats\n",num);
- while(1){
- sem_wait(&mutex);
- sem_wait(&sema[num]);
- sem_wait(&sema[(num+1)%PHILO_NUM]);
- sem_post(&mutex);
- printf("Philosopher %d eats\n",num);
- sem_post(&sema[num]);
- sem_post(&(sema[(num+1)%PHILO_NUM]));
- sleep(1);
- }
- return ((void *)0);
- }
哲学家问题解决:
comments:5个人5副刀叉。4个人吃饭毕竟不向5个人,肯定至少有一个会吃到,然后放下,然后其他的人就不会一直hold,所以让其中之一先sleep一下。即不会死锁。
但是从理论上讲,只是开始的时候,4人同吃,不会出现死锁。
但是过了id=0,sleep之后,又变成5个人同吃。还是可能存在死锁的可能。
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#define PHILOS 5
#define DELAY 5000
#define FOOD 50
void *philosopher (void *id);
void grab_chopstick(int ,
int ,
char *);
void down_chopsticks (int ,
int);
int food_on_table();
pthread_mutex_t chopstick[PHILOS];
pthread_t philo[PHILOS];
pthread_mutex_t food_lock;
int sleep_seconds=10;
int main (int argn,char **argv)
{
int i;
if (argn==2)
sleep_seconds=atoi(argv[1]);
pthread_mutex_init(&food_lock,NULL);
for (i=0;i<PHILOS;i++)
pthread_mutex_init(&chopstick[i],NULL);
for (i=0;i<PHILOS;i++)
pthread_create(&philo[i],NULL,philosopher,(void*)i);
for (i=0;i<PHILOS;i++)
pthread_join(philo[i],NULL);
return 0;
}
void *
philosopher (void *num)
{
int id;
int i,left_chopstick,right_chopstick,f;
id=(int)num;
printf("Philosopher %d is done thinking and now ready to eat\n ",id);
right_chopstick=id;
left_chopstick=id+1;
//wrap around the chopsticks
if (left_chopstick==PHILOS)
left_chopstick=0;
while (f=food_on_table()) {
/*thanks to philosophers#1 who would like to take a nap
*before picking up the chopsticks,the other philosophers
*may be able to eat their dishes and not deadlock
*/
if (id==0)
sleep(sleep_seconds);
grab_chopstick(id,right_chopstick,"right");
usleep(DELAY *(FOOD -f +1));
grab_chopstick(id,left_chopstick,"left");
printf("Philosopher %d:eating\n",id);
usleep(DELAY *(FOOD -f +1));
down_chopsticks(left_chopstick,right_chopstick);
}
printf("Philosopher %d is done eating \n",id);
return (NULL);
}
int food_on_table ()
{
static int food=FOOD;
int myfood;
pthread_mutex_lock(&food_lock);
if(food>0) {
food--;
}
myfood=food;
pthread_mutex_unlock(&food_lock);
return myfood;
}
void grab_chopstick(int phi1,
int c,