Attention: 打开相关代码链接
1. 互斥锁:
说白了就是可以是线程之间或者进程之间互斥访问共享资源!
函数:
pthread_mutex_init
初始化一个互斥量
pthread_mutex_lock
给一个互斥量加锁
pthread_mutex_trylock
在锁已经被占据时返回EBUSY而不是挂起
pthread_mutex_unlock
解锁
加锁后只有加锁权限的线程或者进程才可以进行操作,其他的要
访问共享资源就只能是wait等待... ...
关于初始化问题有两种方法:
1.直接静态设置pthread_mutex_t量为PTHREAD_MUTEX_INITIALIZER
2.可以动态设置使用函数pthread_mutex_inti( ... )
2. 初始化和回收互斥锁
#include<pthread.h>
>>>>>:
intpthread_mutex_init( pthread_mutex_t * mutex, const
pthread_mutexattr_t * attr
);
参数:mutex
互斥量
attr
互斥锁属性
若成功则返回0,否则返回错误编号。
>>>>>:
intpthread_mutex_destroy( pthread_mutex_t * mutex);
参数:mutex
互斥量
若成功则返回0,否则返回错误编号。
3. 对互斥量加减锁:
#include<pthread.h>
intpthread_mutex_lock(pthread_mutex_t*mutex);
//!> 加锁
intpthread_mutex_trylock(pthread_mutex_t*mutex);
//!>
//在锁已经被占据时返回EBUSY而不是挂起等
intpthread_mutex_unlock(pthread_mutex_t*mutex);
//!> 去锁
若成功则返回0,否则返回错误编号。
4. 上面的测试代码我们知道对于初始化时的属性都是设置为NULL的,
也就是pthread_mutex_init( &g_mutex, NULL);
但是很多时候是不可以的NULL的,所以下面就是解决mutex属性
pthread_mutexattr_t
#include<pthread.h>
intpthread_mutexattr_init( pthread_mutexattr_t * attr );
//!> 初始化属性
intpthread_mutexattr_destroy( pthread_mutexattr_t * attr );
//!> 回收
若成功返回0,若失败返回错误编号。
注意:
pthread_mutexattr_init将属性对象的值初始化为缺省值。并分配属性对象占用的内
存空间。
注意pshared属性:
它的取值可以是PTHREAD_PROCESS_PRIVATE(缺省值,表示由这个属性对象创建
的互斥锁只能在进程内使用)或PTHREAD_PROCESS_SHARED。
互斥量属性分为共享互斥量属性和类型互斥量属性。
>>>>>:
pthread_mutexattr_getpshared和pthread_mutexattr_setpshared函数可以获得和修
改共享互斥量属性。
>>>>>:
pthread_mutexattr_gettype和pthread_mutexattr_settype函数可以获得和修改类型互
斥量属性。
5. 获得/修改共享互斥量属性:
#include<pthread.h>
intpthread_mutexattr_getpshared(const pthread_mutexattr_t *restrictattr, int
*restrictshared );
//!> 获得共享互斥量属性,由shared带出
intpthread_mutexattrattr_ setpshared (
constpthread_mutexattr_t *restrict attr,int
pshared);
//!> 设置共享互斥属性,有shard决定
若成功返回0,若失败返回错误编号。
注意:shared的取值可以是
PTHREAD_PROCESS_SHARED
PTHREAD_PROCESS_PRIVATE
附录:如果互斥锁属性对象的pshared属性被置PTHREAD_PROCESS_SHARED。
那么由这个属性对象创建的互斥锁将被保存在共享内存中,可以被多个进程中的
线程共享。如果pshared属性被置为PTHREAD_PROCESS_PRIVATE,那么只有和
创建这个互斥锁的线程在同一个进程中的线程才能访问这个互斥锁。
6. 获得/修改类型互斥量属性
#include<pthread.h>
#intpthread_mutexattr_settype (pthread_mutexattr_t * attr, intkind);
//!> 设置类型互斥类型
#intpthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind);
//!> 获得类型互斥属性
若成功返回0,若失败返回错误编号。
类型:
缺省的互斥锁类型属性是:
PTHREAD_MUTEX_DEFAULT。
合法的类型属性值有:
PTHREAD_MUTEX_NORMAL:
>: 这种类型的互斥锁不会自动检测死锁。
>: 如果一个线程试图对一个互斥锁重复锁定,将会引起这个线程的死锁。
>: 如果试图解锁一个由别的线程锁定的互斥锁会引发不可预料的结果。
>: 如果一个线程试图解锁已经被解锁的互斥锁也会引发不可预料的结果。
PTHREAD_MUTEX_ERRORCHECK:
>: 这种类型的互斥锁会自动检测死锁。
>: 如果一个线程试图对一个互斥锁重复锁定,将会返回一个错误代码。
>: 如果试图解锁一个由别的线程锁定的互斥锁将会返回一个错误代码。
>: 如果一个线程试图解锁已经被解锁的互斥锁也将会返回一个错误代码。
PTHREAD_MUTEX_RECURSIVE:
>: 如果一个线程对这种类型的互斥锁重复上锁,不会引起死锁。
>: 一个线程对这类互斥锁的多次重复上锁必须由这个线程来重复相同数量的解
锁,这样才能解开这个互斥锁,别的线程才能得到这个互斥锁。
>: 如果试图解锁一个由别的线程锁定的互斥锁将会返回一个错误代码。
>: 如果一个线程试图解锁已经被解锁的互斥锁也将会返回一个错误代码。
>: 这种类型的互斥锁只能是进程私有的(作用域属性为
PTHREAD_PROCESS_PRIVATE)
PTHREAD_MUTEX_DEFAULT:
>: 这种类型的互斥锁不会自动检测死锁。
>: 如果一个线程试图对一个互斥锁重复锁定,将会引起不可预料的结果。
>: 如果试图解锁一个由别的线程锁定的互斥锁会引发不可预料的结果。
>: 如果一个线程试图解锁已经被解锁的互斥锁也会引发不可预料的结果。
>: POSIX标准规定,对于某一具体的实现,可以把这种类型的互斥锁定义为其他
类型的互斥锁。
相当注意:
1、互斥量需要时间来加锁和解锁。锁住较少互斥量的程序通常运行得更快。所
以,互斥量应该尽量少,够用即可,每个互斥量保护的区域应则尽量大。
2、互斥量的本质是串行执行。如果很多线程需要领繁地加锁同一个互斥量,则
线程的大部分时间就会在等待,这对性能是有害的。如果互斥量保护的数
据(或代码)包含彼此无关的片段,则可以特大的互斥量分解为几个小的互斥量
来提高性能。这样,任意时刻需要小互斥量的线程减少,线程等待时间就会
减少。所以,互斥量应该足够多(到有意义的地步),每个互斥量保护的区域则
应尽量的少。
3、POSIX线程锁机制的Linux实现都不是取消点,因此,延迟取消类型的线程不
会因收到取消信号而离开加锁等待。
4、线程在加锁后解锁前被取消,锁将永远保持锁定状态。因此如果在关键区段
内有取消点存在,或者设置了异步取消类型,则必须在退出回调函数中解
锁。
5、锁机制不是异步信号安全的,也就是说,不应该在信号处理过程中使用互斥
锁,否则容易造成死锁。