源码笔记之互斥锁

本文依托源码,分析 Linux 下互斥锁的实现,包含函数pthread_mutex_initpthread_mutex_destroypthread_mutex_lockpthread_mutex_trylockpthread_mutex_unlock等。


环境

  • Ubuntu 16.04 x86_64
  • Glibc 2.28, POSIX Thread
  • Gcc 5.4.0

互斥锁

简单来说,互斥锁是一种用于多线程编程中,防止两个线程同时对同一公共资源(比如全局变量)进行读写的机制;每个公共资源都对应于一个可称为” 互斥锁” 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。

实现

pthread_mutex_t

pthread_mutex_t 类型定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/* Data structures for mutex handling.  The structure of the attribute
type is not exposed on purpose. */
typedef union
{
struct __pthread_mutex_s
{
int __lock;
unsigned int __count;
int __owner;
#ifdef __x86_64__
unsigned int __nusers;
#endif
/* KIND must stay at this position in the structure to maintain
binary compatibility. */
int __kind;
#ifdef __x86_64__
short __spins;
short __elision;
__pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV 1
/* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER. */
# define __PTHREAD_SPINS 0, 0
#else
unsigned int __nusers;
__extension__ union
{
struct
{
short __espins;
short __elision;
# define __spins __elision_data.__espins
# define __elision __elision_data.__elision
# define __PTHREAD_SPINS { 0, 0 }
} __elision_data;
__pthread_slist_t __list;
};
#endif
} __data;
char __size[__SIZEOF_PTHREAD_MUTEX_T];
long int __align;
} pthread_mutex_t;

pthread_mutex_trylockpthread_mutex_lock 的非阻塞版本。

关键成员:

  • __lockmutex 状态,0 表示未占用,1 表示占用;
  • __count: 用于可重入锁,记录 owner 线程持有锁的次数;
  • __ownerowner 线程 ID
  • __kind: 记录 mutex 的类型,有以下几个取值:
    1
    2
    3
    4
      PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。
      PTHREAD_MUTEX_RECURSIVE_NP,可重入锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。
      PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程重复请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型相同。
      PTHREAD_MUTEX_ADAPTIVE_NP,自适应锁,自旋锁与普通锁的混合。

Mutex可以分为递归锁(recursive mutex)和非递归锁(non-recursive mutex)。可递归锁也可称为可重入锁(reentrant mutex),非递归锁又叫不可重入锁(non-reentrant mutex)。

二者唯一的区别是,同一个线程可以多次获取同一个递归锁,不会产生死锁。而如果一个线程多次获取同一个非递归锁,则会产生死锁。

Windows下的Mutex和Critical Section是可递归的。Linux下的pthread_mutex_t锁默认是非递归的。可以显示的设置PTHREAD_MUTEX_RECURSIVE属性,将pthread_mutex_t设为递归锁。

pthread_mutex_init就是初始化上述的pthread_mutex_t内存结构 哪个文件

pthread_mutex_init

pthread_mutex_destroy

pthread_mutex_lock

pthread_mutex_trylock

pthread_mutex_unlock

知识点:
__attribute_noinline__

参考:


forthebadge

微信公众号同步更新,微信搜索"AnSwEr不是答案"或者扫描二维码,即可订阅。
AnSwEr(Weijie Yuan) wechat