网络编程----互斥量和锁

一、互斥量mutex
多线程可以考虑同一时间只有一个线程访问数据。互斥量(mutex)就是一把锁。

多个线程只有一把锁一个钥匙,谁上的锁就只有谁能开锁。当一个线程要访问一个共享变量时,先用锁把变量锁住,然后再操作,操作完了之后再释放掉锁,完成。

当另一个线程也要访问这个变量时,发现这个变量被锁住了,无法访问,它就会一直等待,直到锁没了,它再给这个变量上个锁,然后使用,使用完了释放锁,以此进行。

这个即使有多个线程同时访问这个变量,也好象是对这个变量的操作是顺序进行的。

互斥变量使用特定的数据类型:pthread_mutex_t,使用互斥量前要先初始化,

pthread_mutex_t
pthread_mutex_t 类型,其本质是一个结构体,为简化理解,应用时可忽略其实现细节,简单当成整数看待。
pthread_mutex_t mutex:变量mutex只有两种取值0、1;

互斥量初始化
a)、POSIX定义了一个宏PTHREAD_MUTEX_INITIALIZER来静态初始化互斥锁,方法如下:

pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
在LinuxThreads实现中,pthread_mutex_t是一个结构,而PTHREAD_MUTEX_INITIALIZER则是一个结构常量。

b)、动态方式是采用pthread_mutex_init()函数来初始化互斥锁,API定义如下:

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)

其中mutexattr用于指定互斥锁属性(见下),如果为NULL则使用缺省属性。

加锁与解锁
lock与unlock:

lock尝试加锁,如果加锁不成功,线程阻塞,阻塞到持有该互斥量的其他线程解锁为止。
unlock主动解锁,同时将阻塞到该锁上所有线程全部唤醒,至于哪个线程先被唤醒取决于优先级,调度。默认:先阻塞、先唤醒。
例如:T1 T2 T3 T4 使用一把mutex锁,T1加锁成功,其他线程均阻塞,直至T1解锁,T1解锁后,T2 T3 T4均被唤醒,并自动再次尝试加锁。

避免死锁
产生死锁的情况较多,如一个线程对变量a加锁后,试图对变量b加锁,另一个线程对变量b加了锁,试图对a加锁,这时两个线程都不释放锁,加不会加锁成功,造成两个线程处于死锁状态。

可以在设计中避免死锁的发生。如使用 pthread_mutex_timedlock函数,该函数允许线程阻塞特定时间,如果加锁失败就会返回ETIMEDOUT。函数原型如下:

#include <pthread.h>
#include <time.h>

int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex, const struct timesec *restrict tsptr);

锁操作:
pthread_mutex_destroy ()注销一个互斥锁

加锁 pthread_mutex_lock()、
解锁pthread_mutex_unlock()
测试加锁 pthread_mutex_trylock()三个

等待和激发:

 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)

等待条件有两种方式:条件等待pthread_cond_wait()和计时等待pthread_cond_timedwait(),
其中计时等待方式如果在给定时刻前条件没有满足,则返回ETIMEOUT,结束等待,其中abstime以与time()系统调用相同意义的绝对时间形式出现,0表示格林尼治时间1970年1月1日0时0分0秒。
无论哪种等待方式,都必须和一个互斥锁配合,以防止多个线程同时请求pthread_cond_wait()、pthread_cond_timedwait()的竞争条件(Race Condition)。mutex互斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP),且在调用pthread_cond_wait()前必须由本线程加锁(thread_mutex_lock()),而在更新条件等待队列以前,mutex保持锁定状态,并在线程挂起进入等待前解锁。在条件满足从而离开pthread_cond_wait()之前,mutex将被重新加锁,以与进入pthread_cond_wait()前的加锁动作对应。

激发条件有两种形式,
pthread_cond_signal()激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个;
而pthread_cond_broadcast()则激活所有等待线程。

3、处理流程
pthread_cond_wait使用前必须由本线程调用pthread_mutex_lock加锁
pthread_mutex_lock(&mtx);
pthread_cond_wait(&cond,&mtx);
pthread_mutex_unlock(&mtx);
pthread_cond_wait内部处理流程:解锁—>阻塞休眠—>唤醒—>加锁

相关锁链接

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值