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函数。示例代码

时间: 2024-11-05 17:25:03

linux下的同步与互斥的相关文章

Linux 下的同步机制

2017-03-10 回想下最初的计算机设计,在单个CPU的情况下,同一时刻只能由一个线程(在LInux下为进程)占用CPU,且2.6之前的Linux内核并不支持内核抢占,当进程在系统地址运行时,能打断当前操作的只有中断,而中断处理完成后发现之前的状态是在内核,就不触发地调度,只有在返回用户空间时,才会触发调度.所以内核中的共享资源在单个CPU的情况下其实不需要考虑同步机制,尽管表面上看起来是多个进程在同时运行,其实那只是调度器以很小的时间粒度,调度各个进程运行的结果,事实上是一个伪并行.但是随

Linux驱动之同步、互斥、阻塞的应用

同步.互斥.阻塞的概念: 同步:在并发程序设计中,各进程对公共变量的访问必须加以制约,这种制约称为同步. 互斥机制:访问共享资源的代码区叫做临界区,这里的共享资源可能被多个线程需要,但这些共享资源又不能被同时访问,因此临界区需要以某种互斥机制加以保护,以确保共享资源被互斥访问. 阻塞与非阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起,调用线程只有在得到结果之后才会返回.非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程,而是直接返回. 在按键驱动的例子中,如果有多个应用程序调用按键

Linux下线程同步的几种方法

Linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 锁机制是同一时刻只允许一个线程执行一个关键部分的代码.  1. 初始化锁 int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr); 其中参数 mutexattr 用于指定锁的属性(见下),如果为NULL则使用缺省属性. 互斥锁的属性在创建锁的时候指定,在LinuxThreads实

linux下文件同步利器rsync

rsync rsync是linux下的数据备份工具,支持远程同步.本地复制. 这是一篇rsync简单的使用文章,很多rsync的认识不足,更多的rsync知识请 到rsync官网研读:https://rsync.samba.org/how-rsync-works.html rsyrsync是系统自带的(至少2.6内核是这样的),如果不是自己编译的内核应该是自带. 检查一个安装 rpm -qa | grep rsync 如果没有安装,自己下载rpm包或者使用yum安装,这里就不演示. 配置rsyn

linux下svnsync同步版本库配置

svnsync可以方便的把另一个源svn版本同步到指定版本库中,为多版本库应用提供方便. 示例: (版本库所存目录  /svn/  下) 源版本库:  svn://196.168.0.1/testA      同步用户:sync_source 密码:123456 目标版本库: svn://196.168.0.2/testB    同步用户:sync 密码:123456 源版本库用于开发编辑提交等应用,目标版本库只能可读用于上线备份等应用. 进入目标服务器: 编辑sync同步必要hooks脚本pr

Linux下多线程编程之互斥锁、条件变量、信号量

1.进程创建 int pthread_create (pthread_t * thread_id, __const pthread_attr_t * __attr, void *(*__start_routine) (void *), void *__restrict __arg); 第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数. 一个实例: void *producer(void *args); pthread_

Linux下进程的同步互斥实例——生产者消费者

linux下的同步和互斥 Linux sync_mutex 看的更舒服点的版本= = https://github.com/Svtter/MyBlog/blob/master/Linux/pthread/Linux_producer_consumer.md Semaphore.h 一份好文档,胜读十年书 本文参考了诸多资料,百度百科,cplusplus等 首先介绍一个头文件 #include <semaphore.h> 这里面包含了大多数的所需要使用的信号量. 包含: int sem_init

Linux环境下线程的同步与互斥以及死锁问题

由于本次要讨论操作系统的死锁问题,所以必须先研究的是linux环境下的线程同步与互斥 先看下面的代码 大家猜想输出应该是什么呢? 结果是下面这个样子 好吧,似乎并没有什么区别... 那么下面再看这段代码(请无视并忽略屏蔽的内容...) 大家猜想正确的结果是什么呢?5000,10000? 好吧,或许你们都错了. 在运行了一段时间后,它的结果是这样的. 是不是又对又错? 为什么呢? 这就是因为程序中printf语句作用:本身是库函数,所以必须进行系统调用,必须进入内核进行切换,有很大概率形成数据的混

转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥) 介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可以看作是Unix进程的表亲,同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等.但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage). 一