天天看點

多線程程式設計——條件變量

#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
/* 靜态方式初始化一個互斥鎖和一個條件變量 */
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
/* 指向線程控制塊的指針 */
static pthread_t tid1;
static pthread_t tid2;
/* 函數傳回值檢查 */
static void check_result(char* str,int result)
{
	if (0 == result)
	{
		printf("%s successfully!\n",str);
	}
	else
	{
		printf("%s failed! error code is %d\n",str,result);
	}
}
/* 生産者生産的結構體資料,存放在連結清單裡 */
struct node
{
	int n_number;
	struct node* n_next;
};
struct node* head = NULL; /* 連結清單頭,是共享資源 */
/* 消費者線程入口函數 */
static void* consumer(void* parameter)
{
	struct node* p_node = NULL;
	pthread_mutex_lock(&mutex); /* 對互斥鎖上鎖 */
	while (1)
	{
		while (head == NULL) /* 判斷連結清單裡是否有元素 */
		{
			pthread_cond_wait(&cond,&mutex); /* 嘗試擷取條件變量 */
		}
		/*
		pthread_cond_wait()會先對mutex解鎖,
		然後阻塞在等待隊列,直到擷取條件變量被喚醒,
		被喚醒後,該線程會再次對mutex上鎖,成功進入臨界區。
		*/
		p_node = head; /* 拿到資源 */
		head = head->n_next; /* 頭指針指向下一個資源 */
		/* 列印輸出 */
		printf("consume %d\n",p_node->n_number);
		free(p_node); /* 拿到資源後釋放節點占用的記憶體 */
	}
	pthread_mutex_unlock(&mutex); /* 釋放互斥鎖 */
	return 0;
}
/* 生産者線程入口函數 */
static void* product(void* patameter)
{
	int count = 0;
	struct node *p_node;
	while(1)
	{
		/* 動态配置設定一塊結構體記憶體 */
		p_node = (struct node*)malloc(sizeof(struct node));
		if (p_node != NULL)
		{
			p_node->n_number = count++;
			pthread_mutex_lock(&mutex); /* 需要操作head這個臨界資源,先加鎖 */
			p_node->n_next = head;
			head = p_node; /* 往連結清單頭插入資料 */
			pthread_mutex_unlock(&mutex); /* 解鎖 */
			printf("produce %d\n",p_node->n_number);
			pthread_cond_signal(&cond); /* 發信号喚醒一個線程 */
			usleep(2); /* 休眠2微秒 */
		}
		else
		{
			printf("product malloc node failed!\n");
			break;
		}
	}
}
/* 使用者應用入口 */
int application_init()
{
	int result;
	/* 建立生産者線程,屬性為預設值,入口函數是product,入口函數參數為NULL*/
	result = pthread_create(&tid1,NULL,product,NULL);
	check_result("product thread created ",result);
	/* 建立消費者線程,屬性為預設值,入口函數是consumer,入口函數參數是NULL */
	result = pthread_create(&tid2,NULL,consumer,NULL);
	check_result("consumer thread created ",result);
	return 0;
}
int main()
{
	int i ;
	application_init();
	i=100;
	do{
		sleep(1);
	}while(i--);
}

           

運作結果:

-bash-3.2$ ./app

product thread created successfully!

consumer thread created successfully!

produce 0

consume 0

produce 1

consume 1

produce 2

consume 2

produce 3

consume 3

produce 4

consume 4

produce 5

consume 5

produce 6

consume 6

produce 7

consume 7

produce 8

consume 8

produce 9

consume 9

produce 10

consume 10

produce 11

consume 11

produce 12

consume 12

produce 13

consume 13

produce 14

consume 14

produce 15

consume 15

produce 16

consume 16

繼續閱讀