linux网络编程之POSIX信号量、自旋锁、读写锁

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

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值