posix信号量
system v 信号量只能用于进程间同步,而posix信号量除了可以进程间同步,还可以线程间同步。systemv 信号量每次PV操作可以是N,但Posix信号量每次PV只能是1。除此之外,posix信号量还有命名和匿名之分(man7 sem_overview):
1、命名信号量
名字以/somename形式分辨,只能有一个/ ,且总长不能超过NAME_MAX- 4(一般是251)。
需要用sem_open函数创建或打开,PV操作分别是sem_wait和 sem_post,可以使用sem_close 关闭,删除用sem_unlink。
2、匿名信号量
存放在一块共享内存中,如果是线程共享,这块区域可以是全局变量;如果是进程共享,可以是systemv 共享内存(shmget 创建,shmat映射),也可以是 posix 共享内存(shm_open 创建,mmap映射)。
匿名信号量必须用sem_init初始化,sem_init 函数其中一个参数pshared决定了线程共享还是进程共享,也可以用sem_post和sem_wait 进行操作,在共享内存释放前,匿名信号量要先用sem_destroy销毁。
二、互斥锁
对 于多线程的程序,访问冲突的问题是很普遍的,解决的办法是引入互斥锁(Mutex,MutualExclusiveLock),获得锁的线程可以完成“读-修改-写”的操作,然后释放锁给其它线程,没有获得锁的线程只能等待而不能访问共享数据,这样“读-修改-写”三 步操作组成一个原子操作,要么都执行,要么都不执行,不会执行到中间被打断,也不会在其它处理器上并行做这个操作。
Mutex用pthread_mutex_t类型的变量表示,pthread_mutex_init函数对Mutex做初始化,参数attr设定Mutex的属性,如果attr为NULL则表示缺省属性,具体看结构体:
struct pthread_mutexattr_t
{
enum lock_type // 使用pthread_mutexattr_settype来更改
{
PTHREAD_MUTEX_TIMED_NP [default]//当一个线程加锁后,其余请求锁的线程形成等待队列,在解锁后按优先级获得锁。
PTHREAD_MUTEX_ADAPTIVE_NP // 动作最简单的锁类型,解锁后所有线程重新竞争。
PTHREAD_MUTEX_RECURSIVE_NP // 允许同一线程对同一锁成功获得多次。当然也要解锁多次。其余线程在解锁时重新竞争。
PTHREAD_MUTEX_ERRORCHECK_NP // 若同一线程请求同一锁,返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP动作相同。
} type;
} attr;
用 pthread_mutex_init函数初始化的Mutex可以用pthread_mutex_destroy销毁。如果Mutex变量是静态分配的 (全局变量或static变量),也可以用宏定义PTHREAD_MUTEX_INITIALIZER来初始化,相当于用 pthread_mutex_init初始化并且attr参数为NULL。
一 个线程可以调用pthread_mutex_lock获得Mutex,如果这时另一个线程已经调用pthread_mutex_lock获得了该 Mutex,则当前线程需要挂起等待,直到另一个线程调用pthread_mutex_unlock释放Mutex,当前线程被唤醒,才能获得该 Mutex并继续执行。
POSIX信号量相关函数:
sem_open
sem_close
sem_unlink
sem_init
sem_destroy
sem_wait
sem_post
POSIX互斥锁:
pthread_mutex_init
pthreaad_mutex_lock
pthread_mutex_unlock
pthread_mutex_destroy
自旋锁:
是专为防止多处理器并发而引入的一种锁。
自旋锁类似于互斥锁,它的性能比互斥锁更高。
自旋锁与互斥锁很重要的一个区别在于,线程在申请自旋锁的时候,线程不会被挂起,它处于忙等待的状态。
pthread_spin_init
pthread_spin_destroy
pthread_spin_lock
pthread_spin_unlock
读写锁:
只要没有线程持有给定的读写锁用于写,那么任意数目的线程可以持有读写锁用于读;
仅当没有线程持有某个给定的读写锁用于读或用于写时,才能分配读写锁用于写;
读写锁用于读称为共享锁,读写锁用于写称为排它锁
一个读写锁同时只能有一个写者或多个读者(与CPU数相关),但不能同时既有读者又有写者。
一次只有一个线程可以占有写模式的读写锁, 但是可以有多个线程同时占有读模式的读写锁. 正是因为这个特性,
当读写锁是写加锁状态时, 在这个锁被解锁之前, 所有试图对这个锁加锁的线程都会被阻塞.
当读写锁在读加锁状态时, 所有试图以读模式对它进行加锁的线程都可以得到访问权, 但是如果线程希望以写模式对此锁进行加锁, 它必须直到知道所有的线程释放锁.
读写锁适合于对数据结构的读次数比写次数多得多的情况. 因为, 读模式锁定时可以共享, 以写模式锁住时意味着独占, 所以读写锁又叫共享-独占锁.
pthread_rwlock_init
pthread_rwlock_destroy
int pthread_rwlock_rdlock
int pthread_rwlock_wrlock
int pthread_rwlock_unlock