linux互斥锁的基本知识

来源:互联网 发布:ubuntu登陆后桌面假死 编辑:程序博客网 时间:2024/05/27 09:47
1 竞争条件
  • 当一个线程访问一个数据结构的时候,另一个线程也访问同一个数据结构,这时就出现了竞争条件——两个线程(也可能是多个)竞争对同一个资源(如全局变量,尤其是链表、哈希表等)的访问。
  • 当其中一个线程处理到一部分的时候,另外的线程可能进入了对同一数据的处理,而且出于调度的原因,它运行的比前一个更快;这时,同样的处理可能就出现了多次。
        例如,一个代表任务列表的单向链表(队列),一个线程从当前元素中读出了下一个任务,并发现下一个任务不是空,准备将此一个任务置为NULL并执行任务; 这时,调度使得这个线程停下来,另一个线程也从当前元素中读出了下一个任务,当然下个任务仍然不是空值,这个线程也将要执行下一个任务。这样,在某些不幸 的情况下,这个任务被执行了两次。
        更为不幸的情况下,执行任务的过程中线程被中断,此时另一个线程释放了任务的内存,那么执行中的线程会导致段错误。在比较“幸运”的情况下,这些事情可能从来也不发生;但是当程序运行在负荷很高的系统中时,这个bug就会凸现出来。

2 互斥锁的基本概念

互斥锁,是一种信号量,常用来防止两个进程或线程在同一时刻访问相同的共享资源。可以保证以下三点:

  • 原子性:把一个互斥量锁定为一个原子操作,这意味着操作系统(或pthread函数库)保证了如果一个线程锁定了一个互斥量,没有其他线程在同一时间可以成功锁定这个互斥量。
  • 唯一性:如果一个线程锁定了一个互斥量,在它解除锁定之前,没有其他线程可以锁定这个互斥量。
  • 非繁忙等待:如果一个线程已经锁定了一个互斥量,第二个线程又试图去锁定这个互斥量,则第二个线程将被挂起(不占用任何cpu资源),直到第一个线程解除对这个互斥量的锁定为止,第二个线程则被唤醒并继续执行,同时锁定这个互斥量。
3 互斥锁的属性
3.1 作用域

函数pthread_mutexattr_setpshared用来设置互斥锁的作用域。
互斥锁变量可以是进程专用的变量,也可以是跨越进程边界的变量。
  • PTHREAD_PROCESS_SHARED:多进程之间,具有该属性的互斥锁可以在多个进程中的线程之间共享。
  • PTHREAD_PROCESS_PRIVATE:其所属进程内部,只有创建本互斥锁的线程所在的进程内的线程才能够使用该互斥锁变量。该值是缺省值。
3.2 类型
pthread_mutexattr_settype用来设置指定互斥锁的类型属性。类型属性的缺省值为 PTHREAD_MUTEX_DEFAULT。
  • PTHREAD_MUTEX_NORMAL:不提供死锁检测。尝试重新锁定互斥锁会导致死锁。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或未锁定,则将产生不确定的行为。
  • PTHREAD_MUTEX_ERRORCHECK:提供错误检查。如果某个线程尝试重新锁定的互斥锁已经由该线程锁定,则将返回错误。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或者未锁定,则将返回错误。
  • PTHREAD_MUTEX_RECURSIVE:该互斥锁会保留锁定计数这一概念。线程首次成功获取互斥锁时,锁定计数会设置为 1。线程每重新锁定该互斥锁一次,锁定计数就增加 1。线程每解除锁定该互斥锁一次,锁定计数就减小 1。 锁定计数达到 0 时,该互斥锁即可供其他线程获取。如果某个线程尝试解除锁定的互斥锁不是由该线程锁定或者未锁定,则将返回错误。
  • PTHREAD_MUTEX_DEFAULT:尝试以递归方式锁定该互斥锁将产生不确定的行为。对于不是由调用线程锁定的互斥锁,如果尝试解除对它的锁定,则会产生不确定的行为。如果尝试解除锁定尚未锁定的互斥锁,则会产生不确定的行为。
4 基本使用
pthread_mutex_t mutex;                   //定义锁
pthread_mutex_init(&mutex, NULL);   //默认属性初始化锁
pthread_mutex_lock(&mutex);           //申请锁
...
pthread_mutex_unlock(&mutex);       //释放锁

0 0
原创粉丝点击