mutexmutex上面说过,如果系统中存在资源共享,线程之间存在竞争,没有合理的同步机制,就会出现数据混乱。为了实现同步机制,Linux提供了多种方式,其中一种方式就是互斥锁mutex(也叫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);函数功能:初始化一个互斥体(mutex)互斥量,初始值可视为1;参数介绍:mutex:传出参数,调用时要将&mutex传给函数;这里有一个特殊的关键字:restrict。它的作用只是用来限制指针,告诉编译器,所有修改内存中指向的指针内容的操作,都只能通过这个指针来完成。它不能被除此指针以外的其他变量或指针修改。比如定义一个pthread_mutex_t指针,赋给mutex的值,用来修改mutex指向的内存,这是不允许的。attr:互斥属性。它是一个传入参数,通常传递NULL,表示使用默认属性(即:线程间共享)。互斥锁的初始化有两种方式:1.静态初始化:如果互斥锁是静态分配的,即定义为全局变量,或者用static关键字修饰,可以直接用宏初始化。例如pthead_mutex_tmuetx=PTHREAD_MUTEX_INITIALIZER;2.动态初始化:如果mutex互斥量定义为局部变量,则应使用动态初始化。例如pthread_mutex_init(&mutex,NULL)pthread_mutex_destroy函数函数原型:intpthread_mutex_destroy(pthread_mutex_t*mutex);函数功能:销毁一个互斥量pthread_mutex_lock函数函数原型:intpthread_mutex_lock(pthread_mutex_t*mutex);函数功能:锁定共享资源。可以理解为mutex--(或-1);如果锁定不成功,该线程将阻塞,直到持有互斥量的其他线程被解锁。注意:访问共享资源前先锁定,访问后立即解锁。锁的“粒度”应该越小越好。pthread_mutex_unlock函数函数原型:intpthread_mutex_unlock(pthread_mutex_t*mutex);function功能:解锁共享资源。可以理解为mutex++(或+1);解锁时,所有阻塞在锁上的线程都会被唤醒。至于先唤醒哪个线程,取决于优先级和调度。默认情况下:最先阻塞的线程会最先被唤醒。pthread_mutex_trylock函数原型:intpthread_mutex_trylock(pthread_mutex_t*mutex);功能:尝试锁定共享资源。它与pthread_mutex_lock函数的区别在于,在使用锁函数对共享资源进行加锁时,如果加锁不成功,线程将被阻塞;而如果使用trylock,则当前线程在加锁不成功时不会被阻塞,而是立即返回一个描述互斥量情况的值。死锁:一个线程试图锁定同一个互斥体A两次。线程1拥有锁A,请求锁B;线程2拥有锁B并请求锁A(时间(NULL));while(1){pthread_mutex_lock(&mutex);printf("你好");//标准输出是共享资源sleep(rand()%3);//此时会失去CPUprintf("world!\n");pthread_mutex_unlock(&mutex);睡眠(兰德()%3);}returnNULL;}intmain(){pthread_ttid;诠释n=5;srand(时间(NULL));pthread_mutex_init(&mutex,NULL);pthread_create(&tid,NULL,tfn,NULL);while(n--){pthread_mutex_lock(&mutex);printf("你好");睡眠(兰德()%3);printf("世界!\n");pthread_mutex_unlock(&mutex);睡眠(兰德()%3);}pthread_cancel(tid);pthread_join(tid,NULL);pthread_mutex_destroy(&mutex);return0;}更多精彩内容请关注公众号良旭Linux,在公众号回复1024免费获得5T技术资源资料,包括:Linux,C/C++,Python,RaspberryPi,Embedded,Java,ArtificialIntelligence等最后,最近有很多朋友找我要一份Linux学习路线图,所以结合自己的经验,利用业余时间熬夜了一个月,编了一本电子书。无论你是面试还是自我提升,相信都会对你有所帮助!免费送给大家,只求大家给我点个赞!电子书|LinuxDevelopmentLearningRoadmap也希望有小伙伴可以和我一起把这本电子书做得更完美!获得?希望老铁们来个三连击,让更多人看到这篇文章。推荐阅读:干货|程序员和高级架构师免费发送工件的必备资源|支持搜索的资源网站
