Linux 线程间的同步与互斥
在线程并发执行的时候,我们需要保证临界资源的安全访问,防止线程争抢资源,造成数据二义性。
线程同步: 条件变量
为什么使用条件变量?
对临界资源的时序可控性,条件满足会通知其他等待操作临界资源的线程,类似信号。 场景:T-DAY展会排队参观/生产者消费者模型
条件变量是什么?
是一种同步机制,一个线程用于修改这个变量使其满足其它线程继续往下执行的条件,其它线程则接收条件已经发生改变的信号。
条件变量操作?
初始化和销毁
pthread_cond_wait
条件不满足 会释放锁并阻塞等待 , 这个函数是原子性操作:1.将线程放入条件等待队列 2.释放锁
条件满足 则线程会被唤醒并加锁
pthread_cond_signal 一对一唤醒
唤醒等待队列中的一个线程
pthread_cond_broadcast 广播唤醒
唤醒等待队列中的全部线程
为什么等待和解锁需要原子操作/为什么条件变量要使用互斥锁?
因为pthread_cond_wait中的锁是为了保护条件变量,防止错过信号,如果等待解锁不是原子性操作,比如线程A先解锁,此时CPU时间片切换到线程B,线程B加锁并发送条件变量信号,此时再切换到线程A,线程A还来不及等待就错过了信号,就可能会永久阻塞下去。所以,等待和解锁必须是原子性操作。
为什么需要while循环判断临界资源是否存在?
在一对多的情况下,生产者发送一个信号,等待的线程被唤醒并加锁,但是只有一个线程能加锁,其他线程就会阻塞等待锁,如果这个线程用完了临界资源,其他线程不进行判断就继续往下走,是不合理的。
singnal要先解锁还是后解锁?
如果先解锁,锁被没有阻塞等待的线程拿到了,再把临界资源使用了,解锁后的singal就没意义了,也就是虚假唤醒;
先singal唤醒,再让唤醒的线程争抢锁,在linux下,有两个队列,一个是cond_wait,一个是mutex_lock,singal只是让cond_wait上的线程转移到mutex_lock,不会返回用户空间,这样能提高效率。
线程互斥: 互斥锁
为什么使用互斥锁?
对临界资源同时间唯一访问,保护临界资源防止修改。 场景:黄牛抢票
互斥锁是什么?
是一个0/1计数器,1代表有资源能操作,0代表没有资源可以操作。
互斥锁操作?
初始化和销毁
加锁---如果计数为1,置0,进行需要的操作;如果计数为0,则阻塞等待计数变为1
解锁---计数置为1
Linux 线程间的同步与互斥的更多相关文章
- 嵌入式开发之hi3519---进程线程间的同步和互斥,条件变量、信号了、互斥锁等
sem_post 最安全 sem 有序,会卡顿 阻塞 mutex 无序,不能同步 http://blog.chinaunix.net/uid-20671208-id-4935154.html ht ...
- vc++高级班之多线程篇[7]---线程间的同步机制②
//示例代码: CStringArray g_ArrString; UINT __cdecl ThreadProc(LPVOID lpParameter) { int startIdx = (int ...
- Java并发之线程间的同步协作与通信协作
1,Monitor监视器与syncrhoized实现原理 1.1:Monitor Monitor是一个同步工具,相当于操作系统中的互斥量(mutex),即值为1的信号量. 它内置与每一个Object对 ...
- vc++高级班之多线程篇[6]---线程间的同步机制①
①.线程同步的必要性: int g_Num = 0; UINT __cdecl ThreadProc(LPVOID lpParameter) { for (int idx = 0; idx &l ...
- linux线程间同步方式总结梳理
线程间一般无需特别的手段进行通信,由于线程间能够共享数据结构,也就是一个全局变量能够被两个线程同时使用.只是要注意的是线程间须要做好同步! 使用多线程的理由: 1. 一个是和进程相比,它是一种非常&q ...
- Linux线程间同步的几种方式
信号量 信号量强调的是线程(或进程)间的同步:"信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在sem_wait的时候,就阻塞 ...
- linux线程间同步方式汇总
抽空做了下linux所有线程间同步方式的汇总(原生的),包含以下几个: 1, mutex 2, condition variable 3, reader-writer lock 4, spin loc ...
- Linux线程的信号量同步
信号量和互斥锁(mutex)的区别:互斥锁只允许一个线程进入临界区,而信号量允许多个线程同时进入临界区. 不多做解释,要使用信号量同步,需要包含头文件semaphore.h. 主要用到的函数: int ...
- linux 线程间发送信号
线程间通过 pthread_kill(thid,signo)给指定的thid线程发送signo信号. 创建线程与线程屏蔽字顺序 1. pthread_create(); pthread_sigm ...
随机推荐
- JavaScript == 与 === 区别
1.对于 string.number 等基础类型,== 和 === 是有区别的 a)不同类型间比较,== 之比较 "转化成同一类型后的值" 看 "值" 是否相等 ...
- Java之创建文件并写入数据
应用场景:以OJ项目为例,创建对应的.in或.out文件,并将相关的数据写入. 核心代码如下: /** * 创建文件 * @param data * @param basedir * @param n ...
- mysql左连接查询结果不准确
现有四张表 表(1)res_resource_catalog 表(2)res_catalog_classify 表(3)res_resource_classify 表(4)res_resource_m ...
- OpenTK学习笔记:C#的中开发OpenGL程序的4种开源封包库SharpGL、CsGL、OpenTK、Tao框架的简单对比
最近要在C#的语言环境下开发OpenGL程序,参考了网上的博客论坛http://www.cnblogs.com/hanyonglu/archive/2012/06/12/2546581.html,总结 ...
- C# Area区域配置,修改默认路由
1.右键项目新建文件夹 Areas 2.先把项目分类包好,建两个文件夹,放Controller和View,Model也可以放在这里 因为项目启动默认打开的是Home/Index ,我把它放在了Webs ...
- linux系统错误码大全
#define EPERM 1 /* Operation not permitted */ #define ENOENT 2 /* No such file or directory */ #defi ...
- HTML+CSS实现鼠标点上去动画效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Sequelize模糊查询
const Sequelize = require('sequelize'); const Op = Sequelize.Op; User.findAll({ raw: true, order: [ ...
- docker 运行 sqlserver
docker 运行 sqlserver docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=sa123456' -e 'MSSQL_PID=Deve ...
- 上传下载execl
ajax上传execl + easyexecl解析execl <!DOCTYPE html> <html> <head> <meta charset=&quo ...