mutexmutex前面说过,如果系统中存在资源共享,线程之间存在竞争,没有合理的同步机制,就会出现数据混乱。为了实现同步机制,Linux提供了多种方式,其中之一就是互斥锁mutex(也叫mutex)。互斥锁的具体实现如下:每个线程在对共享资源进行操作之前都尝试加锁,只有加锁成功后才能读写共享资源,操作完成后解锁。互斥并不是为了消除竞争。其实资源还是共享的,线程还是在竞争的,只是通过这种“锁”机制,把对共享资源的访问变成了互斥操作,也就是说,一个线程操作了这个资源,当这个资源被加锁时,其他线程无法对其进行操作,从而消除了与时间相关的错误。从互斥量的实现机制可以看出,同一时刻只能有一个线程持有锁。如果有多个线程同时持有锁,那就没意义了。但是,这种锁定机制不是强制性的。互斥量本质上是操作系统提供的“建议锁”(也称为“合作锁”)。当程序中有多个线程访问共享资源时推荐使用该机制。因此,即使有互斥量,如果其他线程不遵循这种锁机制访问共享数据,仍然会发生数据混乱。所以为了避免这种情况,所有访问共享资源的线程都必须使用相同的锁机制。主要应用函数:pthread_mutex_init函数、pthread_mutex_destroy函数、pthread_mutex_lock函数、pthread_mutex_trylock函数、pthread_mutex_unlock函数。以上五个函数的返回值分别是:成功返回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,表示使用默认属性(即:线程间共享)。mutexmutex的初始化有两种方式:静态初始化:如果mutexmutex是静态分配的,即:定义为全局变量,或者用static关键字修饰,可以直接使用宏初始化。例如pthead_mutex_tmuetx=PTHREAD_MUTEX_INITIALIZER;动态初始化:如果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函数的区别在于,在使用lock函数对共享资源进行加锁时,如果加锁不成功,线程将被阻塞;而如果使用trylock,则当前线程在加锁不成功时不会被阻塞,而是立即返回一个描述互斥量情况的值。死锁:一个线程试图锁定同一个互斥体A两次。线程1拥有锁A,请求锁B;线程2拥有锁B并请求锁A;while(1){pthread_mutex_lock(&mutex);printf("你好");//标准输出是共享资源sleep(rand()%3);//这里printf("world!n");pthread_mutex_unlock(&mutex);睡眠(rand()%3);}返回NULL;}intmain(){pthread_ttid;intn=5;srand(time(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);睡眠(rand()%3);}pthread_cancel(tid);pthread_join(tid,NULL);pthread_mutex_destroy(&mutex);返回0;}
