##互斥量mutex

前文提及linux arg系统中假如存在资源共享,线程间存在竞争,而且没有合理的同步机制的话,会出现数据混乱的现象。为了实现同步机制,Linux中提供了多种方法,其中一种方法为互斥锁mutex(亦称之为互斥量)。

互斥量的具体实现方法为:每位线程在对共享资源操作前都尝试先加锁,成功加锁后才可以对共享资源进行读写操作,操作结束后解锁。

互斥量不是为了清除竞争,实际上,资源还是共享的,线程间也还是竞争的,只不过通过这些“锁”机制就将共享资源的访问弄成互斥操作,也就是说一个线程操作这个资源时,其它线程难以操作它linux虚拟主机,因而去除与时间有关的错误。

从互斥量的实现机制我们可以看出,同一时刻,只能有一个线程持有该锁。假如有同时有多个线程持有该锁,那就没有实际意义了。

然而,这些锁机制不是强制的,互斥锁实质上是操作系统提供的一把“建议锁”(又称“协同锁”),建议程序中有多线程访问共享资源的时侯使用该机制。

为此,虽然有了mutex,其它线程倘若不依照这些锁机制来访问共享数据的话,仍然会导致数据混乱。所以为了防止这些情况,所有访问该共享资源的线程必须采用相同的锁机制。

主要应用函数:

pthread_mutex_init函数​pthread_mutex_destroy函数​pthread_mutex_lock函数​pthread_mutex_trylock函数​pthread_mutex_unlock函数

以上5个函数的返回值都是:成功返回0,失败返回错误号。

在Linux环境下,类型pthread_mutex_t其本质是一个结构体。并且为了简化理解,应用时可忽视其实现细节,简单当作整数看待。mutex通常以下边形式定义:

pthread_mutex_tmutex;

变量mutex只有两种取值1、0。

##pthread_mutex_init函数

函数原型:

intpthread_mutex_init(pthread_mutex_trestrictmutex,constpthread_mutexattr_trestrictattr);

函数作用:

linux arg_linux arg_linux arg

初始化一个互斥锁(互斥量)mutex,年率可视为1;

参数介绍:

mutex:传出参数,调用时应传&mutex给该函数;

这儿有个关键字比较特殊:restrict。它的作用只用于限制表针,告诉编译器,所有更改该表针指向显存中内容的操作,只能通过本表针完成。不能通过除本表针以外的其他变量或表针更改。例如说,再定义个pthread_mutex_t的表针,将其形参为mutex的值,想要用它来更改mutex所指向的显存,这是不容许的。

attr:互斥量属性。是一个传入参数,一般传NULL,表示使用默认属性(即:线程间共享)。

对于互斥量mutex的初始化有两种形式:

1.静态初始化:

假如互斥锁mutex是静态分配的,即:定义为全局变量红旗linux下载,或加了static关键字修饰,可以直接使用宏进行初始化。e.g.pthead_mutex_tmuetx=PTHREAD_MUTEX_INITIALIZER;

2.动态初始化:

假如互斥锁mutex定义为局部变量,则应采用动态初始化。e.g.pthread_mutex_init(&mutex,NULL)

##pthread_mutex_destroy函数

函数原型:

intpthread_mutex_destroy(pthread_mutex_t*mutex);

函数作用:

销毁一个互斥锁

pthread_mutex_lock函数

函数原型:

linux arg_linux arg_linux arg

intpthread_mutex_lock(pthread_mutex_t*mutex);

函数作用:

对共享资源进行加锁。可理解为将mutex--(或-1);假如加锁不成功,则该线程将阻塞,直至持有该互斥量的其他线程解锁为止。注意:在访问共享资源前加锁,访问结束后立刻解锁。锁的“粒度”应越小越好。

pthread_mutex_unlock函数

函数原型:

intpthread_mutex_unlock(pthread_mutex_t*mutex);

函数作用:

对共享资源解锁。可理解为将mutex++(或+1);在解锁的同时,会将阻塞在该锁上的所有线程全部唤起,至于那个线程先被唤起,取决于优先级、调度。默认情况下:先阻塞的线程会先被唤起。

##pthread_mutex_trylock函数

函数原型:

intpthread_mutex_trylock(pthread_mutex_t*mutex);

函数作用:

对共享资源尝试加锁。它与pthread_mutex_lock函数的区别是,使用lock函数对共享资源进行加锁时linux arg,假若加锁不成功,则线程就阻塞;而倘若使用trylock,则加锁不成功时不会阻塞当前线程,而是立刻返回一个值来描述互斥锁的状况。

死锁:

线程企图对同一个互斥量A加锁两次。线程1拥有A锁,恳请获得B锁;线程2拥有B锁,恳请获得A锁

#include 
#include 
#include 
#include 

linux arg_linux arg_linux arg

pthread_mutex_t mutex; void *tfn(void *arg) { srand(time(NULL)); while(1) { pthread_mutex_lock(&mutex); printf("hello "); // 标准输出为共享资源 sleep(rand() % 3); // 在此时会失去CPU printf("world!n"); pthread_mutex_unlock(&mutex); sleep(rand() % 3); } return NULL; } int main() { pthread_t tid; int n = 5; srand(time(NULL)); pthread_mutex_init(&mutex, NULL); pthread_create(&tid, NULL, tfn, NULL); while(n--) { pthread_mutex_lock(&mutex); printf("HELLO "); sleep(rand() % 3); printf("WORLD!n"); pthread_mutex_unlock(&mutex); sleep(rand() % 3); } pthread_cancel(tid); pthread_join(tid, NULL); pthread_mutex_destroy(&mutex); return 0; }

>2020精选阿里/腾讯等一线大厂笔试、简历、进阶、电子书「**良许Linux**」后台回复「**资料**」免费获取

####看完的都是真爱,点个赞再走呗?您的「三连」就是良许持续创作的最大动力!

1.关注**原创**「**良许Linux**」,第一时间获取最新Linux干货!

2.后台回复【资料】【面试】【简历】获取精选一线大厂笔试、自我提高、简历等资料。

3.关注我的博客:[]()

Tagged:
Author

这篇优质的内容由TA贡献而来

刘遄

《Linux就该这么学》书籍作者,RHCA认证架构师,教育学(计算机专业硕士)。

发表回复