linux下的同步与互斥
linux下的同步与互斥
谈到linux的并发,必然涉及到线程之间的同步和互斥,linux主要为我们提供了几种实现线程间同步互斥的
机制,本文主要介绍互斥锁,条件变量和信号量。互斥锁和条件变量包含在pthread线程库中,使用时需要包含
<pthread.h>头文件。而使用信号量时需要包含<semaphore.h>头文件。
1.互斥锁
类型声明:pthread_mutex_t mutex;
对互斥量的初始化:
程序在使用pthread_mutex_t之前需要先对其进行初始化,对于静态分配的pthread_mutex_t变量来说,
只要将PTHREAD_MUTEX_INITIALIZER赋给变量就行了,语句如下:
static pthread_mutex_t mutex=PTHREAD_mutex_INITIALIZER;
而对于动态分配或没有默认互斥属性的互斥变量来说,要调用pthread_mutex_init函数来执行初始化工
作。函数声明如下:
int pthread_mutex_init(pthread_mutex_t* mutex,const pthread_mutexattr_t* attr);
mutex是指向一个互斥量的指针,attr是指向一个属性结构体的指针,为NULL时使用默认属性。
需要注意的是pthread_mutex_init函数只能恰好执行一次,重复执行的结果是未定义的。
对互斥量的操作:
int pthread_mutex_lock(pthread_mutex_t* mutex);//对互斥量执行锁定操作
int pthread_mutex_unlock(pthread_mutex_t* mutex);//对互斥量执行解锁操作
对互斥量的销毁:
int pthread_mutex_destroy(pthread_mutex_t* mutex);//
使用方法:
以下代码用互斥量来保护一个临界区:
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;//初始化
pthread_mutex_lock(&mutex);//获得锁
/*critical section code*/
pthread_mutex_unlock(&mutex);//释放锁
通常比较适用的方法是将编写一组访问临界区的函数,将锁定调用都放在这些函数中,这是确保对对象的拍他
性访问的一种方法,这样锁定机制对调用线程就是透明的了。
2.条件变量
有时,我们可能需要让线程在某个条件满足之前一直等待,在未使用条件变量之前,您可能会使用忙等待,如
下列代码:
while(x!=y);
这样的方式,然而这种占着茅坑不拉屎的行为是非常不被提倡的。因此,我们引入条件变量的概念来是线程在
某个条件不满足是进入挂起状态。
类型声明:pthread_cond_t cond;
对条件变量的初始化:
程序在使用pthread_cond_t变量之前必须对其进行初始化。对于静态分配的pthread_cond_t变量来说,
只要将PTHREAD_COND_INITIALIZER赋给变量就星了,语句如下:
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
对于动态分配的或没有默认属性的变量来说,就要调用pthread_cond_init函数来执行初始化。函数声明如下:
int pthread_cond_init(pthread_cond_t* cond,const pthread_cond_attr_t* attr);
cond是指向一个条件变量的指针,attr是指向一个属性结构体的指针,为NULL时使用默认属性。
对条件变量的操作:
int pthread_cond_wait(pthread_cond_* cond,pthread_mutex_t* mutex);//使线程阻塞于某个条件。
int pthread_cond_signal(pthread_cond_t* cond);//唤醒某个阻塞在cond上的线程。
对条件变量的销毁:
int pthread_cond_destroy(pthread_cond_t* cond);
使用方法:
条件变量是与断言或条件的测试一同调用的,以此来实现将条件变量关联到某个断言上去。通常线程会对
一个条件进行测试,如果失败,就会调用pthread_cond_wait函数将线程阻塞。示例代码如下:
pthread_mutex_lock(&mutex);
while( a<b )
pthread_cond_wait(&cond,&mutex);
pthread_mutex_unlock(&mutex);
调用线程应该在它测试或调用pthread_cond_wait之前获得一个互斥量,以避免在测试条件的时候有其他
线程改写条件中变量的值。pthread_cond_wait函数中第二个参数是一个互斥量类型的指针,线程在调用
pthread_cond_wait后会隐式的原子地释放mutex互斥量并阻塞,允许其他线程获得互斥量并修改断言中
的变量。当线程成功的从pthread_cond_wait中返回时,它就再次拥有了互斥量,并且不用显式的重新获
得互斥量。
当其他线程修改了断言中变量的值后可以调用pthread_cond_signal函数来唤醒一个等待在某个断言成真
的线程。也可以使用pthread_cond_broadcast(pthread_cond_t*)函数来唤醒所有等待在某个条件变量
上的线程。在修改断言中出现的任一变量之前要获得互斥量。示例代码如下:
pthread_mutex_lock(&mutex);
a++;
pthread_cond_signal(&cond);//pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
3.信号量
信号量是一个整型变量,它带有两个原子操作wait和signal。wait操作还可以被称为down、P操作。signal操
作还可以被称为up、V、post操作。
如果S大于0,wait操作就在一个原子操作中对其进行减量运算。如果S等于0,wait操作就就在一个原子操作中
测试S,阻塞调用程序,将调用程序放入wait的等待队列中。
如果有线程在信号量上阻塞,则S必然等于0,signal操作就会解除对某一个等待线程的阻塞。如果S大于0,即
没有线程阻塞在信号量上,signal就对S进行增量操作。
可以把信号量理解为临界区中资源的可用数量,wait表示对资源的申请,当没有可用资源时信号量为0,signal
表示线程使用资源后,对资源的释放。
下面介绍几种通过信号量来控制线程按某种顺序执行的方法:
1.线程1中a先于线程2中b执行[S初始话为0]
Process 1:
a;
signal(&S);
Process 2:
wait(&S);
b;
2.线程1中a于线程2中b语句交替执行[S,Q初始化为1]
Process 1:
while(1){
wait(&S);
a;
signal(&Q);
}
Process 2:
while(1){
wait(&Q);
b;
signal(&S);
}
可通过让S为0Q为1,或让S为1Q为0,来保证让a或b先执行。
需要注意的是,为了避免申请多个资源发生死锁,应按照相同的顺序申请资源,这里公司面试的时候经常会被
问到。
linux中信号量有无名信号量和命名信号量之分,无名信号量可用于线程之间的同步和互斥,命名信号量可用
于进程间的通信,命名信号量与命名管道相似,以文件的形式存储于磁盘上。
无名信号量:
类型声明:
sem_t sem;
初始化:
int sem_init(sem_t* sem,int pshared,int value);
参数pshared为0,表示信号量只能由初始化这个信号量的进程中的线程使用。
value表示要将sem初始化的值。value不能为负。
操作:
int sem_post(sem_t* sem);//signal操作
int sem_wait(sem_t* sem);//wait操作
销毁:
int sem_destroy(sem_t* sem);
使用方法:
通常先由主线程调用sem_init对信号量进行初始化。然后在其他线程中调用post或wait函数。示例代码
- 本文来自:Linux教程网
linux下的同步与互斥的更多相关文章
- linux下数据同步、回写机制分析
一.前言在linux2.6.32之前,linux下数据同步是基于pdflush线程机制来实现的,在linux2.6.32以上的版本,内核彻底删掉了pdflush机制,改为了基于per-bdi线程来实现 ...
- Linux驱动之同步、互斥、阻塞的应用
同步.互斥.阻塞的概念: 同步:在并发程序设计中,各进程对公共变量的访问必须加以制约,这种制约称为同步. 互斥机制:访问共享资源的代码区叫做临界区,这里的共享资源可能被多个线程需要,但这些共享资源又不 ...
- Linux下线程同步的几种方法
Linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 锁机制是同一时刻只允许一个线程执行一个关键部分的代码. 1. 初始化锁 int pthrea ...
- Linux 下的同步机制
2017-03-10 回想下最初的计算机设计,在单个CPU的情况下,同一时刻只能由一个线程(在LInux下为进程)占用CPU,且2.6之前的Linux内核并不支持内核抢占,当进程在系统地址运行时,能打 ...
- linux下自动同步internet时间
linux下很简单直接一句即可: ntpdate time.nist.gov ntp后面参数为internet时间服务器url或ip即可. 但是ntpdate命令需要root特权,如果做成自动运行每次 ...
- linux下使用线程锁互斥访问资源
linux使用线程锁访问互斥资源: 1.线程锁的创建 pthread_mutex_t g_Mutex; 2.完整代码如下 #include <stdio.h> #include <s ...
- 【Linux多线程】同步与互斥的区别
同步与互斥这两个概念经常被混淆,所以在这里说一下它们的区别. 一.同步与互斥的区别 1. 同步 同步,又称直接制约关系,是指多个线程(或进程)为了合作完成任务,必须严格按照规定的 某种先后次序来运行. ...
- linux下主从同步和redis的用法
前言 mariadb其实就是mysql mysql已经被oracle收购,它即将闭源,马上要开始收费了因此还想免费试用开源的数据库mysql,就在centos7上,将mysql分支为mariadb 操 ...
- linux 下svn同步更新钩子
svn服务器搭建:https://www.linuxidc.com/Linux/2017-05/144254.htm SVN版本库中的一个项目:/svn/repositories/test/ 网站目录 ...
随机推荐
- Django之mysql表单操作
在Django之ORM模型中总结过django下mysql表的创建操作,接下来总结mysql表记录操作,包括表记录的增.删.改.查. 1. 添加表记录 class UserInfo(models.Mo ...
- vc++ windows 开始菜单添加快捷方式
开始菜单创建快捷方式 在windows软件开发中,软件安装过程中总是需要在开始菜单创建快捷方式,下面介绍一种开始菜单创建快捷方式的方法,具体代码如下: /* * 创建快捷方式 * szExePath[ ...
- 剑指offer-第六章面试中的各项能力(n个骰子的点数)
题目:把n个骰子扔到地上,骰子之和为S,输入n,打印s所有可能的值出现的概率. 思路:由于骰子的点数为1~6,因此n个骰子之和的大小为n~6n之间.故可以定义一个数组来存放这6n-n+1个数出现的次数 ...
- Shell编程(二)——shell的基础知识及常用命令
shell的基础知识 一.bash有以下特点: 1.记录命令历史 2.指令和文件名补全 3.别名 alias rm='rm -i' 4.通配符 * 0个或多个字符 ?匹配一个字符 5 输入输出重定向 ...
- 04:sqlalchemy操作数据库 不错
目录: 1.1 ORM介绍(作用:不用原生SQL语句对数据库操作) 1.2 安装sqlalchemy并创建表 1.3 使用sqlalchemy对表基本操作 1.4 一对多外键关联 1.5 sqlalc ...
- js客户端UI框架
Best jQuery UI http://b-jui.com/ jQuery EasyUI http://www.jeasyui.com/ bootstrap学习网: http://www.runo ...
- Cocoa Pod使用总结
1. 背景 CocoaPod是Swift,Objective-C语言编写的Cocoa项目的依赖管理工具.简单点说就是它管理了很多的Swift和Objective-C的库,然后通过CocoaPod可以比 ...
- CAN总线位仲裁技术
CAN总线位仲裁技术 只要总线空闲,任何单元都可以开始发送报文. 要对数据进行实时处理,就必须将数据快速传送,这就要求数据的物理传输通路有较高的速度.在几个站同时需要发送数据时,要求快速地进行总线分配 ...
- keepalived 预防脑裂检测脚本
1 检查vip [root@mysql2 keepalived]# cat /etc/keepalived/check_brain_keepalived.sh #!/bin/bash # 检查脑裂的脚 ...
- python利用scapy模块写一个TCP路由追踪和扫描存活IP的脚本
前言: 没有前言 0x01 from scapy.all import * import sys from socket import * import os from threading impor ...