当前位置:网站首页>Conditional variables for thread synchronization
Conditional variables for thread synchronization
2022-06-26 03:58:00 【StudyWinter】
1 Basic concepts
The conditional variable itself is not a lock ! But it can also cause thread blocking . Usually used with mutex . Provide a meeting place for multithreading .
Conditional variables are used to wait for threads instead of locking them , Conditional variables are often used with mutexes . The reason why conditional variables are used with mutexes , Mainly because an obvious feature of mutex is that it has only two states : Locked and unlocked , Conditional variables can make up for the lack of mutex by allowing a thread to block and wait for another thread to send a signal , So mutexes and conditional variables are usually used together .
When the conditions are met , Threads usually unlock and wait for the condition to change , Once another thread changes the environment variable , It will notify the corresponding environment variable to wake up one or more threads blocked by this condition variable . These awakened threads will be locked again , And test whether the conditions meet . In general, conditional variables are used for synchronization between threads ; When the conditions are not met , Allow one of the execution flows to hang and wait
Reference resources : Detailed explanation of conditional variables _ The breeze is coming Groot The blog of -CSDN Blog _ Condition variables,
2 Why use conditional variables
When a thread preempts a mutex , Threads A The mutex lock was seized , But the conditions are not met , Threads A Will give up the mutex to other threads , Then wait for other threads to wake him up ; Once the conditions are met , The thread can be awakened , And use the mutex to access the shared area . Through this design, the process can run more stably .
3 Function USES
3.1 pthread_cond_init function
effect : Initialize a conditional variable
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
// ginseng 2:attr Table condition variable properties , Usually the default value , Pass on NULL that will do Static initialization and dynamic initialization
// 1 initiate static
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
// 2 dynamic initialization
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);3.2 pthread_cond_destroy function
effect : Destroy a conditional variable
int pthread_cond_destroy(pthread_cond_t *cond);3.3 pthread_cond_wait function ( a key )
effect :( It's very important Three points )
1 Block wait condition variable cond( ginseng 1) Satisfy
2 Release the mastered mutex ( Unlock mutex ) amount to pthread_mutex_unlock(&mutex);
3 When awakened ,pthread_cond_wait When function returns , Unblock and re apply for mutex
pthread_mutex_lock(&mutex);
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);1.2. Two steps for an atomic operation .
3.4 pthread_cond_timedwait function
effect : Wait for a conditional variable for a limited time
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);3.5 pthread_cond_signal function
effect : Wake up at least one thread blocked on a condition variable
int pthread_cond_signal(pthread_cond_t *cond);3.6 pthread_cond_broadcast function
effect : Wake up all threads blocked on condition variables
int pthread_cond_broadcast(pthread_cond_t *cond);
4 Producer consumer model

step :
producer :
(1) The production data ;
(2) Lock pthread_mutex_lock(&mutex);
(3) Place data in public areas ;
(4) Unlock pthread_mutex_unlock(&mutex);
(5) Notifies threads blocking on condition variables pthread_cond_signal()、pthread_cond_brocadcast();
(6) Generate sequential data in a cycle .
consumer :
(1) Create a lock pthread_mutex_t mutex;
(2) Initialize lock pthread_mutex_init(mutex, NULL);
(3) Lock pthread_mutex_lock(&mutex);
(4) Wait condition satisfied
pthread_cond_wait(&cond, &mutex);
Block wait condition variable ;
Unlock ;
----10s;
Lock ;
(5) Access shared data ;
(6) Unlock 、 Release condition variable , Release the lock .
Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
// Simulate with conditional variables [ producer - consumer ] problem
// Linked list as shared data , Need to be protected by mutex
struct Msg
{
int val;
struct Msg *next;
};
// Head node
struct Msg *head;
// Statically initialize mutexes and condition variables
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
// Producer thread
void *producer(void *arg)
{
struct Msg *mp;
while (1)
{
// To apply for space
mp = malloc(sizeof(struct Msg));
// Simulate the production of a product
mp->val = rand() % 1000 + 1;
printf("---produce----------------------:%d\n", mp->val);
// Lock
int res = pthread_mutex_lock(&lock);
if (res != 0)
{
fprintf(stderr, "pthread_mutex_lock producer error:%s\n", strerror(res));
exit(1);
}
// The first interpolation
mp->next = head;
head = mp;
// Unlock
res = pthread_mutex_unlock(&lock);
if (res != 0)
{
fprintf(stderr, "pthread_mutex_unlock producer error:%s\n", strerror(res));
exit(1);
}
// Will wait for a thread on the condition variable to wake up
res = pthread_cond_signal(&has_product);
if (res != 0)
{
fprintf(stderr, "pthread_cond_signal producer error:%s\n", strerror(res));
exit(1);
}
sleep(rand() % 5);
}
}
// Consumer thread
void *consumer(void *arg)
{
struct Msg *mp;
while (1)
{
// Lock
int res = pthread_mutex_lock(&lock);
if (res != 0)
{
fprintf(stderr, "pthread_mutex_lock consumer error:%s\n", strerror(res));
exit(1);
}
// The header node is empty , Indicates that there are no nodes
while (head == NULL)
{
// Consumer is blocking
res = pthread_cond_wait(&has_product, &lock);
if (res != 0)
{
fprintf(stderr, "pthread_cond_wait consumer error:%s\n", strerror(res));
exit(1);
}
}
// Simulate the consumption of a product
mp = head;
head = head->next;
// Unlock
res = pthread_mutex_unlock(&lock);
if (res != 0)
{
fprintf(stderr, "pthread_mutex_unlock consumer error:%s\n", strerror(res));
exit(1);
}
printf("==Consumer:%lu====%d\n", pthread_self(), mp->val);
// Release
free(mp);
sleep(rand() % 5);
}
}
int main(int argc, char **argv)
{
// Create producer and consumer threads
pthread_t pid, cid;
srand(time(NULL));
// Create a producer thread
int res = pthread_create(&pid, NULL, producer, NULL);
if (res != 0)
{
fprintf(stderr, "pthread_create producer error:%s\n", strerror(res));
exit(1);
}
// Create consumer thread
res = pthread_create(&cid, NULL, consumer, NULL);
if (res != 0)
{
fprintf(stderr, "pthread_create consumer error:%s\n", strerror(res));
exit(1);
}
// Recycling producer threads
res = pthread_join(pid, NULL);
if (res != 0)
{
fprintf(stderr, "pthread_join producer error:%s\n", strerror(res));
exit(1);
}
// Recycle consumer threads
res = pthread_join(cid, NULL);
if (res != 0)
{
fprintf(stderr, "pthread_join consumer error:%s\n", strerror(res));
exit(1);
}
return 0;
}perform

5 Multiple consumers
Producers have shorter breaks , Everything else is the same
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
// Simulate with conditional variables [ producer - consumer ] problem
// Linked list as shared data , Need to be protected by mutex
struct Msg
{
int val;
struct Msg *next;
};
// Head node
struct Msg *head;
// Statically initialize mutexes and condition variables
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
// Producer thread
void *producer(void *arg)
{
struct Msg *mp;
while (1)
{
// To apply for space
mp = malloc(sizeof(struct Msg));
// Simulate the production of a product
mp->val = rand() % 1000 + 1;
printf("---produce----------------------:%d\n", mp->val);
// Lock
int res = pthread_mutex_lock(&lock);
if (res != 0)
{
fprintf(stderr, "pthread_mutex_lock producer error:%s\n", strerror(res));
exit(1);
}
// The first interpolation
mp->next = head;
head = mp;
// Unlock
res = pthread_mutex_unlock(&lock);
if (res != 0)
{
fprintf(stderr, "pthread_mutex_unlock producer error:%s\n", strerror(res));
exit(1);
}
// Will wait for a thread on the condition variable to wake up
res = pthread_cond_signal(&has_product);
if (res != 0)
{
fprintf(stderr, "pthread_cond_signal producer error:%s\n", strerror(res));
exit(1);
}
sleep(rand() % 3);
}
}
// Consumer thread
void *consumer(void *arg)
{
struct Msg *mp;
while (1)
{
// Lock
int res = pthread_mutex_lock(&lock);
if (res != 0)
{
fprintf(stderr, "pthread_mutex_lock consumer error:%s\n", strerror(res));
exit(1);
}
// The header node is empty , Indicates that there are no nodes
while (head == NULL)
{
// Consumer is blocking
res = pthread_cond_wait(&has_product, &lock);
if (res != 0)
{
fprintf(stderr, "pthread_cond_wait consumer error:%s\n", strerror(res));
exit(1);
}
}
// Simulate the consumption of a product
mp = head;
head = head->next;
// Unlock
res = pthread_mutex_unlock(&lock);
if (res != 0)
{
fprintf(stderr, "pthread_mutex_unlock consumer error:%s\n", strerror(res));
exit(1);
}
printf("==Consumer:%lu====%d\n", pthread_self(), mp->val);
// Release
free(mp);
sleep(rand() % 5);
}
}
int main(int argc, char **argv)
{
// Create producer and consumer threads
pthread_t pid, cid;
srand(time(NULL));
// Create a producer thread
int res = pthread_create(&pid, NULL, producer, NULL);
if (res != 0)
{
fprintf(stderr, "pthread_create producer error:%s\n", strerror(res));
exit(1);
}
/***********3 Consumers ****************/
// Create consumer thread
res = pthread_create(&cid, NULL, consumer, NULL);
if (res != 0)
{
fprintf(stderr, "pthread_create consumer error:%s\n", strerror(res));
exit(1);
}
// Create consumer thread
res = pthread_create(&cid, NULL, consumer, NULL);
if (res != 0)
{
fprintf(stderr, "pthread_create consumer error:%s\n", strerror(res));
exit(1);
}
// Create consumer thread
res = pthread_create(&cid, NULL, consumer, NULL);
if (res != 0)
{
fprintf(stderr, "pthread_create consumer error:%s\n", strerror(res));
exit(1);
}
// Recycling producer threads
res = pthread_join(pid, NULL);
if (res != 0)
{
fprintf(stderr, "pthread_join producer error:%s\n", strerror(res));
exit(1);
}
// Recycle consumer threads
res = pthread_join(cid, NULL);
if (res != 0)
{
fprintf(stderr, "pthread_join consumer error:%s\n", strerror(res));
exit(1);
}
return 0;
}perform

6 Advantages of conditional variables
Compare with mutex for , Conditional variables can reduce competition .
If used directly mutex, Except producers 、 Consumers should compete with each other in addition to mutual exclusion , Consumers also need competition and mutual exclusion , But if you ( Linked list ) No data in , Competition and mutual exclusion between consumers are meaningless . With the conditional variable mechanism , Only producers complete production , Will cause competition among consumers . Improved program efficiency .
边栏推荐
- Unity移动端游戏性能优化简谱之 以引擎模块为划分的CPU耗时调优
- 816. 模糊坐标
- How to solve the problem that iterative semi supervised training is difficult to implement in ASR training? RTC dev Meetup
- 763. 划分字母区间
- XML parsing bean tool class
- Quanergy welcomes Lori sundberg as chief human resources officer
- matplotlib多条折线图,点散图
- What's wrong with connecting MySQL database with eclipse and then the words in the figure appear
- Camera-memory内存泄漏分析(二)
- 在出海获客这件事上,数字广告投放之外,广告主还能怎么玩儿?
猜你喜欢

Camera-CreateCaptureSession

线程同步之读写锁
![[Flink] a brief analysis of the writing process of Flink sort shuffle](/img/27/01e95b44df46d8bfcb36ab1d746cc2.jpg)
[Flink] a brief analysis of the writing process of Flink sort shuffle

Detr3d multi 2D picture 3D detection framework

. Net core learning journey

【Flink】Flink Sort-Shuffle写流程简析

軟件調試測試的十大重要基本准則

EF core Basics

MySQL advanced part (IV: locking mechanism and SQL optimization)

高性能算力中心 — RoCE — Overview
随机推荐
Question brushing record day01
MapReduce execution principle record
2020 summary: industrial software development under Internet thinking
软件调试测试的十大重要基本准则
I/O 虚拟化技术 — UIO Framework
三元损失英文版
After four years of outsourcing, people are directly abandoned...
【掘金运营套路揭露】真心被掘金的套路....
Dix critères de base importants pour les essais de débogage de logiciels
YOLOv5改进:更换骨干网(Backbone)
Getting started with flask
神经网络学习小记录71——Tensorflow2 使用Google Colab进行深度学习
[collection of good books] from technology to products
ASP. Net startup and running mechanism
English version of ternary loss
An error occurred using the connection to database 'on server' 10.28.253.2‘
What does virtualization mean? What technologies are included? What is the difference with private cloud?
Ieda suddenly cannot find compact middle packages
【LOJ#6718】九个太阳「弱」化版(循环卷积,任意模数NTT)
高性能算力中心 — RoCE — Overview