【Linux】线程同步(条件变量)

(一)条件变量

条件变量提供一种线程间通知机制,当某个共享数据到达一定条件时,会唤醒等待(阻塞的)得到这个共享数据的线程
条件变量与互斥锁结合使用,对临界区资源加锁进行控制的基础上,当条件变量满足条件,会唤醒该线程;执行完毕后解锁;

(二)条件变量的相关接口

头文件: pthread.h

(1)初始化条件变量
int pthread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr);

(2)把某个线程添加到条件变量的等待队列(一种数据结构如:链表)中,等待条件可用
int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex);

注意:

  • 在使用pthread_cond_wait的前后应该加锁控制
    pthread_mutex_lock(&mutex);
    pthread_cond_wait(&cond, &mutex);
    pthread_mutex_unlock(&mutex);
    将线程添加到条件变量的等待队列之前,防止其他线程的添加到条件变量的等待队列产生覆盖

(3)唤醒单个线程
int pthread_cond_signal(pthread_cond_t* cond);

(4)唤醒所有等待的线程
int pthread_cond_broadcast(pthread_cond_t* cond);

3 4 的前后使用互斥锁进行控制
防止唤醒线程的过程中有其他的线程入队/出队


(5)销毁条件变量
int pthread_cond_destroy(pthread_cond_t* cond);

(三)简单使用条件变量

功能描述:

  • 主线程从键盘获取字符串后,唤醒两个新进程其中一个线程输出字符串打印到屏幕上
  • 若输入end开头的字符串,结束所有的线程。

注意点:需要用互斥锁控制的点

  • 多个线程同时进出等待队列
  • 唤醒的过程中有进出等待队列

在这里插入图片描述

  • 代码:
#include <stdio.h>
#include <pthread.h>
#include <string.h>
//创建互斥锁
pthread_mutex_t mutex;

//创建条件变量
pthread_cond_t cond;

void* print_fun1(void* arg)
{
    
    
	char* s = (char*)arg;

	while(1)
	{
    
    
		//加互斥锁
		pthread_mutex_lock(&mutex);
		//添加条件变量到等待队列
		pthread_cond_wait(&cond, &mutex);
		//解互斥锁
		pthread_mutex_unlock(&mutex);

		if(strncmp(s, "end", 3) == 0)
		{
    
    
			break;
		}
		printf("fun1 = %s\n", s);
	}
	pthread_exit(NULL);
}

void* print_fun2(void* arg)
{
    
    
	char* s = (char*)arg;

	while(1)
	{
    
    
		//加互斥锁
		pthread_mutex_lock(&mutex);
		//添加条件变量到等待队列
		pthread_cond_wait(&cond, &mutex);
		//解互斥锁
		pthread_mutex_unlock(&mutex);

		if(strncmp(s, "end", 3) == 0)
		{
    
    
			break;
		}
		printf("fun2 = %s\n", s);
	}
	pthread_exit(NULL);
}

int main()
{
    
    
	//初始化互斥锁
	pthread_mutex_init(&mutex, NULL);
	//初始化条件变量
	pthread_cond_init(&cond, NULL);

	pthread_t ids[2];
	char buff[128] = {
    
    0};

	pthread_create(&ids[0], NULL, print_fun1, (void*)buff);
	pthread_create(&ids[1], NULL, print_fun2, (void*)buff);

	while(1)
	{
    
    
		fgets(buff, 127, stdin);

		buff[strlen(buff) - 1] = '\0';
		
		if(strncmp(buff, "end", 3) == 0)
		{
    
    
			//防止唤醒时,等待队列有进出的线程
			pthread_mutex_lock(&mutex);
			pthread_cond_broadcast(&cond);
			pthread_mutex_unlock(&mutex);
			break;
		}
		
		//防止唤醒时,等待队列有进出的线程
		pthread_mutex_lock(&mutex);
		//输入完成后去唤醒某个线程
		pthread_cond_signal(&cond);
		
		pthread_mutex_unlock(&mutex);
	}

	//等待其他线程退出
	for(int i = 0; i < 2; i++)
	{
    
    
		pthread_join(ids[i], NULL);
	}
	//销毁锁
	pthread_mutex_destroy(&mutex);
	//销毁条件变量
	pthread_cond_destroy(&cond);

	return 0;
}
  • 结果:
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/xiaoxiaoguailou/article/details/121589420