<Linux线程同步>——《Linux》

news/2024/12/3 1:43:06/

 目录

1. Linux线程同步

1.1条件变量

1.2同步概念与竞态条件

1.3条件变量函数

1.4 为什么pthread_ cond_ wait 需要互斥量?

1.5 条件变量使用规范

后记:●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!

                                                                           ——By 作者:新晓·故知


1. Linux线程同步

1.1条件变量

  • 当一个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了。
  • 例如一个线程访问队列时,发现队列为空,它只能等待,只到其它线程将一个节点添加到队列中。这种情况就需要用到条件变量。

1.2同步概念与竞态条件

  • 同步:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问题,叫做同步
  • 竞态条件:因为时序问题,而导致程序异常,我们称之为竞态条件。在线程场景下,这种问题也不难理解

1.3条件变量函数

初始化
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t*restrictattr);
参数:cond:要初始化的条件变量attr:NULL
销毁
int pthread_cond_destroy(pthread_cond_t *cond)
等待条件满足
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);参数:cond:要在这个条件变量上等待mutex:互斥量,后面详细解释
唤醒等待
 int pthread_cond_broadcast(pthread_cond_t *cond);int pthread_cond_signal(pthread_cond_t *cond);

 


#include <iostream>
#include <vector>
#include <string>
#include <functional>
#include <unistd.h>
#include <pthread.h>
using namespace std;// 定义一个条件变量
pthread_cond_t cond;
// 定义一个互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //当前不用,但是接口需要,所以我们需要留下来
vector<function<void()>> funcs;
void show()
{cout << "hello show" << endl;
}
void print()
{cout << "hello print" << endl;
}
// 定义全局退出变量
volatile bool quit = false;
void *waitCommand(void *args)
{pthread_detach(pthread_self());while (!quit){// 执行了下面的代码,证明某一种条件不就绪(现在还没有场景),要我这个线程等待// 三个线程,都会进在条件变量下进行排队pthread_cond_wait(&cond, &mutex); //让对应的线程进行等待,等待被唤醒for(auto &f : funcs){f();}}cout << "thread id: " << pthread_self() << " end..." << endl;return nullptr;
}int main()
{funcs.push_back(show);funcs.push_back(print);funcs.push_back([](){cout << "你好世界!" << endl;});pthread_cond_init(&cond, nullptr);pthread_t t1, t2, t3;pthread_create(&t1, nullptr, waitCommand, nullptr);pthread_create(&t2, nullptr, waitCommand, nullptr);pthread_create(&t3, nullptr, waitCommand, nullptr);while(true){char n = 'a';cout << "请输入你的command(n/q): ";cin >> n;if(n == 'n') pthread_cond_signal(&cond);else break;}//sleep(1);cout << "main thread quit!" << endl;pthread_cond_destroy(&cond);return 0;
}

 

简单案例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
pthread_cond_t cond;
pthread_mutex_t mutex;
void *r1(void *arg)
{while (1){pthread_cond_wait(&cond, &mutex);printf("活动\n");}
}
void *r2(void *arg)
{while (1){pthread_cond_signal(&cond);sleep(1);}
}
int main(void)
{pthread_t t1, t2;pthread_cond_init(&cond, NULL);pthread_mutex_init(&mutex, NULL);pthread_create(&t1, NULL, r1, NULL);pthread_create(&t2, NULL, r2, NULL);pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);
}

 

 

1.4 为什么pthread_ cond_ wait 需要互斥量?

  • 条件等待是线程间同步的一种手段,如果只有一个线程,条件不满足,一直等下去都不会满足,所以必须要有一个线程通过某些操作,改变共享变量,使原先不满足的条件变得满足,并且友好的通知等待在条件变量上的线程。
  • 条件不会无缘无故的突然变得满足了,必然会牵扯到共享数据的变化。所以一定要用互斥锁来保护。没有互斥锁就无法安全的获取和修改共享数据。

 

按照上面的说法,我们设计出如下的代码:先上锁,发现条件不满足,解锁,然后等待在条件变量上不就行了,如下代码:
// 错误的设计
pthread_mutex_lock(&mutex);
while (condition_is_false)
{pthread_mutex_unlock(&mutex);//解锁之后,等待之前,条件可能已经满足,信号已经发出,但是该信号可能被错过pthread_cond_wait(&cond);pthread_mutex_lock(&mutex);
}
pthread_mutex_unlock(&mutex);
  • 由于解锁和等待不是原子操作。调用解锁之后,pthread_ cond_ wait之前,如果已经有其他线程获取到互斥量,摒弃条件满足,发送了信号,那么pthread_ cond_ wait将错过这个信号,可能会导致线程永远阻塞在这个 pthread_ cond_ wait 。所以解锁和等待必须是一个原子操作。
  • int pthread_cond_wait(pthread_cond_ t *cond,pthread_mutex_ t * mutex); 进入该函数后,会去看条件量等于0不?等于,就把互斥量变成1,直到cond_ wait返回,把条件量改成1,把互斥量恢复成原样。

1.5 条件变量使用规范

  • 等待条件代码
 pthread_mutex_lock(&mutex);while (条件为假)pthread_cond_wait(cond, mutex);修改条件pthread_mutex_unlock(&mutex);
  • 给条件发送信号代码
pthread_mutex_lock(&mutex);设置条件为真pthread_cond_signal(cond);pthread_mutex_unlock(&mutex);

后记:
●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!

                                                                           ——By 作者:新晓·故知

 


http://www.ppmy.cn/news/6694.html

相关文章

linux共享内存的使用

共享内存可以由多个程序同时访问的内存&#xff0c;能够避免进程间通信过程中的冗余数据拷贝&#xff0c;是IPC中最快的一种,特别适合用来作大块数据的传输。共享内存可以映射到不同的进程空间&#xff0c;这些进程间的数据传递就不再涉及内核。这个过程其实是把同一块物理内存…

MARKETS AND MARKET LOGIC——The Market‘s Principles (1)

序 没有人确切地知道场内期货交易者比场外交易者有多大的优势。但我们确实知道&#xff0c;无论这种优势是什么&#xff0c;现在都大大减少了&#xff0c;这要归功于J.Peter Steidlmayer、Kevin Koy和CBOT这对你来说是个好消息。这对我们来说是个好消息。作为一家折扣经纪人&am…

C++、python、VS code插件安装与SSH使用

下载按照VS coda 官网&#xff1a;https://code.visualstudio.com 1.安装相关插件 1.中文插件&#xff08;可选&#xff09; MS-CEINTL.vscode-language-pack-zh-hans 2.C插件&#xff08;必选&#xff09; ms-vscode.cpptools 3.ssh 远程&#xff08;必选&#xff09; ms-vs…

Python实现猎人猎物优化算法(HPO)优化支持向量机分类模型(SVC算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 猎人猎物优化搜索算法(Hunter–prey optimizer, HPO)是由Naruei& Keynia于2022年提出的一种最新的优…

十七、Docker Compose容器编排第二篇

在上一篇中我们讲解了容器编排是什么、能干什么、怎么安装、使用步骤&#xff0c;如果没有看的大家可以先看下&#xff1a;https://blog.csdn.net/u011837804/article/details/128335166&#xff0c;然后继续看这一篇&#xff0c;好了&#xff0c;我们继续。 1、Docker Compons…

C++11标准模板(STL)- 算法(std::inner_product)

定义于头文件 <algorithm> 算法库提供大量用途的函数&#xff08;例如查找、排序、计数、操作&#xff09;&#xff0c;它们在元素范围上操作。注意范围定义为 [first, last) &#xff0c;其中 last 指代要查询或修改的最后元素的后一个元素。 计算两个范围的元素的内积…

DSP-离散时间系统

目录 概念&#xff1a; 累加器(Accumulator)&#xff1a; N点滑动滤波器&#xff1a; 离散时间系统的分类 &#xff1a; 线性系统 Linear System 移不变系统 Shift-Invariant Systems 因果系统 Causal System 稳定系统 Stable System 无源&#xff08;passive&#x…

C#语言实例源码系列-伪装文件

专栏分享点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过程中…