线程

一.多线程程序设计

1.线程的创建:pthread_create

int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);

第一个参数:创建的线程的id,是一个传出参数
第二个参数:线程属性 —> 一般为NULL(控制线程的大小)
第三个参数:线程的工作函数,线程创建成功后,从该函数开始执行
第四个参数:给工作函数传的参数

返回值:成功返回0,失败返回erroe number

2.线程ID获取:pthread_self

 pthread_t pthread_self(void);

3.线程结束处理

(1)、调用 pthread_join 回收线程资源(阻塞型,只能回收单个线程)
(2)、使用线程分离,将线程的资源回收工作交给系统(非阻塞型)
(3)、当主线程调用 pthread_exit() 不影响其他线程执行,进程当所有线程都结束以后才退出

注意:线程分离与线程结束时一起使用的

#include <stdio.h>
#include <pthread.h>

// 线程的工作函数
void *worker(void *v)
{	
	// while (1)
	{
		printf ("子线程id: %ld\n", pthread_self());
		sleep(5);
	}
	
	printf ("子线程退出\n");
}

int main()
{
	pthread_t thread;
	pthread_create(&thread, NULL, worker, NULL);

	pthread_detach(thread);  // 线程分离
	
	printf("asdsadsa\n");
	pthread_exit(NULL);      // 主线程结束运行
	
	return 0;
}

主线程运行结束,则进程退出。

全局变量直接作为线程间通信的桥梁。

二.线程同步

(1).信号量

1.创建:sem_init

int sem_init(sem_t *sem, int pshared, unsigned int value);

使用:(一般情况下后两个参数的设定如下)

 sem_t  sem
 sem_init(&sem, 0, 1);

2.控制

int sem_post(sem_t *sem);   // v(+1)
int sem_wait(sem_t *sem);   // p(-1)

3.销毁

int sem_destroy(sem_t *sem);

4.生产者与消费者模型

产生消息的是生产者,处理消息的是消费者,消费者和生产者通过一个缓冲区进行消息传递。

初始值:空:1 满:0

生产者消费者
p(空)p(满)
v(满)v(空)

(2)互斥量(互斥琐)

1.初始化:pthread_mutex_init

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);

2.操作函数

int pthread_mutex_lock(pthread_mutex_t *mutex);//上锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁

3.销毁:pthread_mutex_destroy

int pthread_mutex_destroy(pthread_mutex_t *mutex);  

4.生产者与消费者模型

提高效率

生产者消费者
上锁上锁
p(空)p(满)
解锁解锁
v(满)v(空)
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <string.h>
struct msg
{
	char *buf[10];    // 缓冲区中的数据
	sem_t full;          // 控制消费者进入 
	sem_t empty;         // 控制生产者进入
	int count;           // 资源的个数
}data;    		         // 全局数据

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  // 互斥锁

// 生产者工作函数
void *produce(void *v)
{
	char *buf[] = {"苹果", "梨", "香蕉", "西瓜", "芒果", "葡萄", "菠萝", "红柚"};
	int len = sizeof(buf)/sizeof(buf[0]);
	while (1)
	{
		usleep(100000*(rand()%10+1));
				
		sem_wait(&data.empty);        // 生产者只有当缓冲区为空的时候才能进入
		pthread_mutex_lock(&mutex);

		data.buf[data.count] = buf[rand()%len];
		data.count ++;

		pthread_mutex_unlock(&mutex);
		sem_post(&data.full);         // 生产者放入消息以后,通知消费者去处理
	}
}

// 消费者工作函数
void *consume(void *v)
{
	long num = (long)v;
	
	while (1)
	{
		usleep(100000*(rand()%10+1));
		
		sem_wait(&data.full);          // 消费者只有当缓冲区中有数据的时候才能进入
		pthread_mutex_lock(&mutex);
		
		
		int index = rand() % data.count;
		printf ("%ld 号消费者,吃了一个  %s,  剩余个数:%d\n", num, data.buf[index], data.count-1);
		data.count--;
		char *tmp = data.buf[index];
		data.buf[index] = data.buf[data.count];
		data.buf[data.count] = tmp;
		
		pthread_mutex_unlock(&mutex);
		sem_post(&data.empty);         // 消费者处理完数据以后,通知生产者去放数据
	}
}

int main(int argc, char **argv)
{
	srand((unsigned int)time(NULL));
	long i;
	pthread_t thread;
	for (i = 0; i < 4; i++)
	{
		pthread_create(&thread, NULL, consume, (void*)(i+1));
		pthread_detach(thread);
	}
	
	for (i = 0; i < 4; i++)
	{
		pthread_create(&thread, NULL, produce, NULL);
		pthread_detach(thread);
	}

	sem_init(&data.full, 0, 0);
	sem_init(&data.empty, 0, 10);
	
	pthread_exit(NULL);

	return 0;
}

(3)条件变量

1.初始化:pthread_cond_init

int pthread_cond_init(pthread_cond_t *cond,const pthread_condattr_t *attr);

2.等待:pthread_cond_wait

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

3.触发:pthread_cond_broadcast

int pthread_cond_broadcast(pthread_cond_t *cond);

4.销毁:pthread_cond_destroy

int pthread_cond_destroy(pthread_cond_t *cond);  

#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <string.h>

int resource = 0;   // 资源

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  // 互斥锁
pthread_cond_t cond1;    // 条件变量

// 生产者工作函数
void *produce(void *v)
{
	while (1)
	{
		usleep(100000*(rand()%10+1));
		pthread_mutex_lock(&mutex);
		
		resource += 2;
		
		pthread_cond_broadcast(&cond1);     // 广播
		pthread_mutex_unlock(&mutex);
	}
}


// 消费者工作函数
void *consume(void *v)
{
	while (1)
	{
		usleep(100000*(rand()%10+1));
		pthread_mutex_lock(&mutex);
		while (resource <= 0)
		{
			// 为什么要有循环
			// 因为当线程被唤醒的时候,有可能条件还是不满足的,所以还需要判断一次
			// 1、当等待的时候,会自动解锁
			// 2、当被唤醒的时候,会和其他线程一起抢锁
			pthread_cond_wait(&cond1, &mutex);    // 等待条件满足
		}
		resource--;
		printf ("消费,剩余个数:%d\n",   resource);
		
		pthread_mutex_unlock(&mutex);
	}
	
}

int main(int argc, char **argv)
{
	srand((unsigned int)time(NULL));
	long i;
	pthread_t thread;
	for (i = 0; i < 4; i++)
	{
		pthread_create(&thread, NULL, consume, (void*)(i+1));
		pthread_detach(thread);
	}
	
	// for (i = 0; i < 4; i++)
	//{
		pthread_create(&thread, NULL, produce, NULL);
		pthread_detach(thread);
	//}
	
	pthread_cond_init(&cond1, NULL);
	pthread_exit(NULL);

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值