1. 程式人生 > >[Unix系統程式設計]用訊號量實現哲學家就餐問題

[Unix系統程式設計]用訊號量實現哲學家就餐問題

概述:不知道是訊號量簡單,還是訊號量太簡單,《Advanced Programming in the UNIX Environment》居然不講。有幾個與訊號量相關的系統呼叫,sem_init, sem_wait, sem_trywait, sem_post, sem_getvalue, sem_destory可以通過man sem_init的方式檢視幫助文件,確實比較簡單,就不再贅述。

下面的例子也很簡單,一看就懂,只為練習訊號量的使用。

#include <semaphore.h>
#include <pthread.h>
#include "apue.h"
#include "my_err.h" 

#define N 5 // No. of philosopher
#define M 5 // times of eating
sem_t forks[N];

void * thr_philosopher( void *arg);
int main(int argc, char* argv[])
{
	int i = 0; 
	int err;
	pthread_t tid[N];
	void *tret;
	//initilize semaphore
	for (i = 0; i < N; i++)
	{
		if(sem_init(&forks[i], 0, 1) != 0)
		{
			err_quit("init forks error");
		}
	}
	//create thread
	for (i = 0; i < N; i++)
	{
		err = pthread_create(&tid[i], NULL, thr_philosopher, (void *)i);
		if (err != 0)
		{
			err_quit("can't create thread %d: %s\n", i + 1, strerror(err));
		}
	}

	//get the return value
	for (i = 0; i < N; i++)
	{
		err = pthread_join(tid[i], &tret);
		if (err != 0)
		{
			err_quit("can't join with philosopher %d : %s\n", i + 1,
					strerror(err));
		}
		printf("-------------------philosopher %d has done-------------------\n", (int)tret);
	}

	// delete the source of semaphore
	for (i = 0; i < N; i++)
	{
		err = sem_destroy(&forks[i]);
		if (err != 0)
		{
			err_sys("can't destory semaphore");
		}
	}
	exit(0);
}

void * thr_philosopher( void *arg)
{

	/*
	 * here cann't judge arg == NULL
	 * because (void *)0 will lead to arg = NULL
	 */
	int n = M;
	int i = 0;
	i = (int)arg;
	while ( n-- )
	{
		sleep(1);
		if ( i == N - 1)
		{
			sem_wait(&forks[0]);
			sem_wait(&forks[i]);
		}
		else
		{
			sem_wait(&forks[i]);
			sem_wait(&forks[i + 1]);
		}
		printf("philosopher %d is eating\n", i + 1);
		if ( i == N - 1)
		{
			sem_post(&forks[0]);
			sem_post(&forks[i]);
		}
		else
		{
			sem_post(&forks[i]);
			sem_post(&forks[i + 1]);
		}

	}

	return ((void*)i);
}