读书笔记:第7章 互斥锁和条件变量 (1)

《UNIX网络编程:卷2》P129-P130:图7-2、7-3

单个进程中有多个生产者线程和单个消费者线程。整型数组buff含有被生产和消费的条目。生产者只是把buff[0]设置为0,把buff[1]设置为1,等等。

我们只关心生产者之间的同步。直到所有生产者线程都完成工作后,我们才启动消费者线程。

--------------------------------------------

/*
 * prodcons2.c
 * P129 图7-2 main函数
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>

#define min(x,y)	((x) < (y) ? (x) : (y))
#define MAXNITEM	1000000
#define MAXNTHREADS	100

void *consume(void *arg);
void *produce(void *arg);

int nitems;
struct {
	pthread_mutex_t	mutex;				// 互斥变量
	int				buff[MAXNITEM];
	int				nput;				// buff数组中下一次存放的元素下标
	int				nval;				// 下一次存放的值
} shared = {
	PTHREAD_MUTEX_INITIALIZER			// 初始化互斥变量
};

int main(int argc, char *argv[])
{
	int			n;
	int			i, nthreads, count[MAXNTHREADS];
	pthread_t	tid_produce[MAXNTHREADS], tid_consume;

	if (argc != 3) {
		fprintf(stderr, "usage: prodcons2 <#itmes><#threads>\n");
		exit(1);
	}

	nitems = min(atoi(argv[1]), MAXNITEM);
	nthreads = min(atoi(argv[2]), MAXNTHREADS);

	// 告诉线程系统我们希望并发多少线程,在Linux上无意义,详情man
	//pthread_setconcurrency(nthreads);

	for (i = 0; i < nthreads; i++) {
		count[i] = 0;
		// 创建生产者线程
		if ((n = pthread_create(&tid_produce[i], NULL, produce, &count[i])) != 0) {
			fprintf(stderr, "pthread_create error: %s\n", strerror(n));
			exit(1);
		}
	}

	// 等待所有线程终止
	for (i = 0; i < nthreads; i++) {
		pthread_join(tid_produce[i], NULL);			// 等待生产者线程终止
		printf("count[%d] = %d\n", i, count[i]);
	}

	/* 在所有生产者线程终止后才启动消费者线程 */

	// 创建消费者线程
	if ((n = pthread_create(&tid_consume, NULL, consume, NULL)) != 0) {
		fprintf(stderr, "pthread_create error: %s\n", strerror(n));
		exit(1);
	}
	pthread_join(tid_consume, NULL);				// 等待消费者线程终止

	exit(0);
}

/*
 * prodcons2.c
 * P130 图7-3 produce和consume函数
 */
void *produce(void *arg)
{
	// 产生数据条目
	for ( ; ; ) {
		pthread_mutex_lock(&shared.mutex);			// 互斥量加锁

		if (shared.nput >= nitems) {
			pthread_mutex_unlock(&shared.mutex);	// 缓冲区满,解锁返回
			return(NULL);
		}
		shared.buff[shared.nput] = shared.nval;
		shared.nput++;
		shared.nval++;
		pthread_mutex_unlock(&shared.mutex);		// 互斥量解锁

		*((int *)arg) += 1;							// 单个线程的生产计数器
	}
}

void *consume(void *arg)
{
	int		i;

	// 验证数组内容
	for (i = 0; i < nitems; i++) {
		if (shared.buff[i] != i)					// 发现错误,则输出
			printf("buff[%d] = %d\n", i, shared.buff[i]);
	}
	return(NULL);
}

--------------------------------------------

编译并运行程序:

$ gcc prodcons2.c -o prodcons2 -Wall -lpthread
$ ./prodcons2 
usage: prodcons2 <#itmes><#threads>
$ ./prodcons2 1000000 5
count[0] = 177255
count[1] = 251844
count[2] = 182261
count[3] = 129766
count[4] = 258874

如果去掉互斥锁:

$ ./prodcons2 6000 3
count[0] = 5998
count[1] = 0
count[2] = 195
buff[5854] = 5862
buff[5859] = 5867
buff[5860] = 5868
buff[5861] = 5869
buff[5862] = 5870
buff[5863] = 5871
....省略n行...

你可能感兴趣的:(读书笔记,《UNIX网络编程》)