Condition variables for communication between Linux threads (17)

1.Conditional variable

Unlike mutexes, condition variables are used for waiting rather than locking, and condition variables themselves are not locks! Condition variables are used to automatically block a thread until a special condition occurs. Usually condition variables and mutex locks are used together. Two actions of the condition variable:
(1) The condition is not satisfied, blocking the thread.
(2) When the condition is met, notify the blocked thread to start working. Type of condition variable: pthreadcondt.

2. Condition variable initialization function

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

Function:
Initialize a condition variable.

Parameters:
cond: pointer to the condition variable to be initialized.
attr: condition variable attribute, usually the default value. You can pass NULL or use static initialization method to initialize the condition variable:

    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

Return value:
success: 0.
failure: non-zero, error number.

3. Release condition variable function

	int pthread_cond_destroy(pthread_cond_t *cond);

Function:
Destroy a condition variable

Parameters:
cond: pointer to the condition variable to be initialized.

Return value:
success: 0.
failure: non-zero, error number.

4. Wait for conditional function

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

Function:
Block waiting for a condition variable.
a) Blocking and waiting for the condition variable cond (reference 1) to satisfy
b) Releasing the mastered mutex lock (unlocking the mutex) is equivalent to pthread_mutex_unlock(&mutex);
where a) b) two steps are an atomic operation.
c) When awakened and the pthread_cond_wait function returns, unblock and re-apply for the mutex pthread_mutex_lock(&mutex);

Parameters:
cond: pointer to the condition variable to be initialized.
mutex: mutex lock.

Return value:
success: 0.
failure: non-zero, error number.

5. Time-limited waiting condition function

	int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct *restrict abstime);

Function:
Wait for a condition variable within a limited time.

Parameters:
cond: pointer to the condition variable to be initialized.
mutex: mutex lock.
abstime: absolute time.

Return value:
success: 0.
failure: non-zero, error number.

6. Wake up the thread waiting on the condition variable

	int pthread_cond_signal(pthread_cond_t *cond);

Function:
wake up at least one thread blocked on the condition variable

Parameters:
cond: Points to the condition variable to be initialized.

Return value:
success: 0.
failure: non-zero, error number.

illustrate:

	int pthreadcondbroadcast(pthreadcondt *cond); 功能: 给阻塞在条件变量上的所有线程发送信号 参数: cond 条件变量的地址

7. Reference code

//=============================================================================
// File Name    : thread_cond.c
// Author       : FengQQ
//
// Description  : 条件变量
// Annotation   : 与互斥锁不同,条件变量是用来等待而不是用来上锁的,
//				  条件变量本身不是锁!条件变量用来自动阻塞一个线程,
//				  直到某特殊情况发生为止。通常条件变量和互斥锁同时使用。
//				  条件变量的两个动作:1)条件不满, 阻塞线程 。
//								      2)当条件满足, 通知阻塞的线程开始工作。
//				  条件变量的类型: pthreadcondt。
//
//				  《条件变量实现生产者与消费者代码》
//
// Created by FengQQ. 2020-10-05
//=============================================================================
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>

#define BUFFER_SIZE		5					//生产库存大小
#define PRODUCT_CNT		30					//产品生产总数

typedef struct product_cons_t
{
    
    
	int buffer[BUFFER_SIZE];				//生产产品值
	pthread_mutex_t lock;					//互斥锁 volatile int
	int readpos,writepos;					//读写位置
	pthread_cond_t notempty;				//条件变量,为空
	pthread_cond_t notfull;					//非满
}Product_Cons_T;

Product_Cons_T product_cons;

void init(Product_Cons_T *p)
{
    
    
	pthread_mutex_init(&p->lock,NULL);		//互斥锁
	pthread_cond_init(&p->notempty,NULL);	//条件变量
	pthread_cond_init(&p->notfull,NULL);	//条件变量
	p->readpos = 0;							//读写位置
	p->writepos = 0;
}

void finish(Product_Cons_T *p)
{
    
    
	pthread_mutex_destroy(&p->lock);		//互斥锁
	pthread_cond_destroy(&p->notempty);		//条件变量
	pthread_cond_destroy(&p->notfull);		//条件变量
	p->readpos = 0;							//读写位置
	p->writepos = 0;
}

//-------------生产一个数据--------------
void put(Product_Cons_T *p,int data)		//输入产品子函数
{
    
    
	pthread_mutex_lock(&p->lock);
	if((p->writepos+1)%BUFFER_SIZE == p->readpos)
	{
    
    
		printf("product wait for not full\r\n");
		pthread_cond_wait(&p->notfull,&p->lock);
	}
	
	p->buffer[p->writepos] = data;
	(p->writepos)++;
	if(p->writepos >= BUFFER_SIZE)
		p->writepos = 0;
	
	pthread_cond_signal(&p->notempty);
	pthread_mutex_unlock(&p->lock);
}
//-------------取出一个数据--------------
int get(Product_Cons_T *p)					//输入产品子函数
{
    
    
	int data;
	
	pthread_mutex_lock(&p->lock);
	if(p->readpos == p->writepos)
	{
    
    
		printf("consumer wait for not empty\r\n");
		pthread_cond_wait(&p->notempty,&p->lock);
	}
	data = p->buffer[p->readpos];
	(p->readpos)++;
	if(p->readpos >= BUFFER_SIZE)
		p->readpos = 0;
	
	pthread_cond_signal(&p->notfull);
	pthread_mutex_unlock(&p->lock);
	
	return data;
}
//-----------------生产者线程-----------------
void *pthread_product(void *arg)
{
    
    
	int n;
	for(n=1;n<=50;++n)
	{
    
    
		sleep(1);
		printf("put the %d product...\r\n",n);
		put(&product_cons,n);
		printf("put the %d product success\r\n",n);
	}
	printf("product stopped\r\n");
	
	return NULL;

}
//-----------------消费者线程-----------------
void *pthread_consumer(void *arg)
{
    
    
	static int cnt = 0;
	int num;
	while(1)
	{
    
    
		sleep(2);
		printf("get product...\r\n");
		num = get(&product_cons);
		printf("get the %d product success\r\n",num);
		if(++cnt == PRODUCT_CNT)
			break;
	}
	printf("consumer stopped\r\n");
	
}

int main(int argc,char *argv[])
{
    
    
	int ret;
	pthread_t ptid1,ptid2;
	
	init(&product_cons);										//初始化相关操作
	
	ret = pthread_create(&ptid1,NULL,pthread_product,NULL);		//创建线程1
	if(ret != 0)
	{
    
    
		printf("create new pthread product failed...\r\n");
		return -1;
	}
	
	ret = pthread_create(&ptid2,NULL,pthread_consumer,NULL);	//创建线程2	
	if(ret != 0)
	{
    
    
		printf("create new pthread consumer failed...\r\n");
		return -1;
	}
	
	ret = pthread_join(ptid1,NULL);								//回收线程1资源
	if(ret != 0)
	{
    
    
		printf("pthread product join failed...\r\n");
	}
	
	ret = pthread_join(ptid2,NULL);								//回收线程2资源
	if(ret != 0)
	{
    
    
		printf("pthread consumer join failed...\r\n");
	}
	
	finish(&product_cons);										//释放相关操作
	
	return 0;
}


Signals for communication between Linux threads (18)

Link: link .(https://blog.csdn.net/qq_39721016/article/details/120478269?spm=1001.2014.3001.5501)

Guess you like

Origin blog.csdn.net/qq_39721016/article/details/120477932