Linux线程同步(线程信号量互斥量)

以下所有信号量和互斥量中的函数返回值都遵循成功返回0。

一、信号量

有两组接口函数用于表示信号量,一组取自POSIX的实时扩展,用于线程。另一组取自系统V信号量,常用于进程同步。本文章是针对第一种信号量的知识点。
信号量是一种特俗的变量,可以增加减少,但对其的访问被保证是原子操作,这样的特殊性保证了一个程序中有两个或者更多的线程试图改变一个信号量的值时,系统将保证所有的操作都将依次执行,如果是普通变量,来自同一个程序中的不同线程的冲突操作所导致的结果是不确定的。

1.1、信号量创建
#include "semaphone.h"

/**
 * sem:信号量句柄
 * pshared:控制信号量的类型(共享选项),
 *		  0 :表示这个信号量是当前进程的局部信号量
 *		其他:表示这个信号量何以在多个进程之间共享
 * value:信号量的初始值
**/
int sem_init(sem_t *sem, int pshared, unsigned int value);

对于第二个参数pshared,控制信号量的共享选项一项可能有的内核并不支持除0之外的其他参数,就是说不支持在多个进程之间共享

1.2、常用信号量控制
#include "semaphore.h"

int sem_post(sem_t* sem);//信号量+1
int sem_wait(sem_t* sem);//信号量-1

sem_wait中值得注意的点:

  • sem_wait函数会等待直到信号量有一个非零值才会开始减法操作 (阻塞)
  • sem_wait对应的信号量的值是2时,调用sem_wait的线程继续执行并sem_wait对应的信号量值变成1.
  • 两个线程同事sem_wait,第三个线程sem_post之后,只有一个线程可以获取到信号量并继续执行,另一个线程将继续阻塞。(这就是文章开始所提到的原子操作,信号量的值在同一时刻永远都只会做+1或者-1的操作)
#include "semaphore.h"

int sem_destroy(sem_t *sem);

该函数的功能是删除信号量并清理该信号量拥有的所有资源,所过尝试清理的信号量正在被线程等待,就会收到一个错误。

1.3、信号量控制补充
#include "semaphore.h"

int sem_trywait(sem_t *sem);

sem_trywait 函数是非阻塞的函数,它会尝试获取获取信号量的值,如果信号量 sem value = 0,不是阻塞住,而是直接返回一个错误 EAGAIN。

#include "semaphore.h"

int sem_getvalue(sem_t *sem, int *sval);

获取信号量 sem 的当前值,把该值保存在 sval,若有 1 个或者多个线程正在调用 sem_wait 阻塞在该信号量上,该函数返回阻塞在该信号量上进程或线程个数。

二、互斥量

互斥量与信号量类似,其主要用于锁住某个对象、代码等,使得每次只能由一个线程访问它。由于其原理和信号量类似,因此不详细描述,仅列出常用接口如下:

2.1 互斥量控制
#include "pyhread.h"
/**
 * 互斥量初始化:
 * mutex:互斥量句柄
 * attr:互斥量的属性,属性控制着互斥量的行为(将在最后描述),一般默认为NULL
**/
int pthread_mutext_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);

/**
 * 互斥量加锁:
 * mutex:互斥量句柄
**/

int pthread_mutex_lock(pthread_mutex_t *mutex);//一直阻塞到互斥量可用为止
int pthread_mutex_trylock(pthread_mutex_t *mutex);//会尝试加锁,通常立即返回,其中另一个线程已持有锁的情况下,调用pthread_mutex_trylock()函数的额错误码是EBUSY

/**
 * 互斥量解锁:
 * mutex:互斥量句柄
**/
int pthread_mutex_unlock(pthread_mutex_t *mutex);

/**
 * 互斥量删除:
 * mutex:互斥量句柄
**/
int pthread_mutex_destroy(pthread_mutex_t *mutex);
2.2 互斥量属性

互斥量有三种属性:
1.进程间共享属性
2. 健壮属性
3. 类型属性

2.2.1 互斥量属性初始化/去初始化
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
2.2.2 进程共享属性

与信号量相同,互斥量也可选是否在进程间共享,可通过检查是否定义了_POSIX_THREAD_PROCESS_SHARED符号来判断系统是否支持该属性。其相关函数如下:

/**
 * 设置/获取进程间共享属性
 * attr:互斥量属性
 * pshared:标志是否在进程间同步该互斥量
 * 			PTHREAD_PROCESS_SHARED:该互斥量就可以用于进程间的同步
**/
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict attr, int *restrict pshared); 
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);
2.2.3 健壮属性(进程间共享互斥量)

该属性用于多进程共享的互斥量(也就是设置了进程间同步属性)。当持有互斥量的进程终止时,需要解决互斥量状态恢复的问题。该属性默认值为PTHREAD_MUTEX_STALLED ,意味着持有互斥量的进程终止时不会有特别的动作。如果设置属性为PTHREAD_MUTEX_ROBUST,则在进程终止后,等待中的线程调用pthread_mutex_lock,会从中返回EOWNERREAD而不是0.

/**
 * 设置/获取进程间健壮属性
 * attr:互斥量属性
 * robust:标志互斥量是否支持该属性
 * 			PTHREAD_MUTEX_STALLED:非健壮
 *			PTHREAD_MUTEX_ROBUST: 健壮
**/
int phtread_mutexattr_getrobust(const pthread_mutexattr_t attr, int *robust)
int phtread_mutexattr_setrobust(pthread_mutexattr_t attr, int *robust)
					
2.2.4 类型属性
/**
 * 设置/获取互斥量类型属性
 * attr:互斥量属性
 * type:标志互斥量支持的类型属性
 *		 PTHREAD_MUTEX_NORMAL:标准互斥量类型,不做特殊的错误检查和死锁检测。
 *		 PTHREAD_MUTEX_ERRORCHECK:此类型提供错误检查。
 *		 PTHREAD_MUTEX_RECURSIVE:递归类型,此种类型允许同一线程在互斥量解锁之前对该互斥量进行多次加锁。递归互斥量维护锁的计数,在解锁次数与加锁次数不同的情况下,不会释放锁。
 *		 PTHREAD_MUTEX_DEFAULT(默认):此类型提供默认特性,操作系统实现时会把它映射到上面三种中的一种上。linux映射到第一种标准类型上。
**/
int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type)
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值