4、自旋锁,自旋锁采用了和互斥量完全不同的策略, 自旋锁加锁失败, 并不会让出CPU, 而是不停地尝试加锁, 直到成功为止。 这种机制在临界区非常小且对临界区的争夺并不激烈的场景下, 效果非常好。自旋锁的效果好, 但是副作用也大, 如果使用不当, 自旋锁的持有者迟迟无法释放锁, 那么, 自旋接近于死循环, 会消耗大量的CPU资源, 造成CPU使用率飙高。 因此, 使用自旋锁时, 一定要确保临界区尽可能地小, 不要有系统调用, 不要调用sleep。 使用strcpy/memcpy等函数也需要谨慎判断操作内存的大小, 以及是否会引起缺页中断。
5、PTHREAD_MUTEX_ADAPTIVE_NP:自适应锁,首先与自旋锁一样, 持续尝试获取, 但过了一定时间仍然不能申请到锁, 就放弃尝试, 让出CPU并等待。 PTHREAD_MUTEX_ADAPTIVE_NP类型的互斥量, 采用的就是这种机制。
6.8死锁和活锁

线程1已经成功拿到了互斥量1, 正在申请互斥量2, 而同时在另一个CPU上,线程2已经拿到了互斥量2, 正在申请互斥量1。 彼此占有对方正在申请的互斥量,结局就是谁也没办法拿到想要的互斥量, 于是死锁就发生了。
6.8.1死锁概念
死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其它进程所占有不会释放的资源而处于一种永久等待的状态。
6.8.2死锁的四个必要条件
1、互斥条件:一个资源只能被一个执行流使用
2、请求与保持条件:一个执行流因请求资源而阻塞时,对已获得的资源不会释放
3、不剥夺条件:一个执行流已获得的资源,在未使用完之前,不能强行剥夺
4、循环等待条件:若干执行流之间形成一种头尾相接的循环等待资源的关系
6.8.3避免死锁
1、破坏死锁的四个必要条件(实际上只能破坏条件2和4)
2、加锁顺序一致(按照先后顺序申请互斥锁)
3、避免未释放锁的情况
4、资源一次性分配
6.8.4活锁
避免死锁的另一种方式是尝试一下,如果取不到锁就返回。
int pthread_mutex_trylock(pthread_mutex_t *mutex);int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,const struct timespec *restrict abs_timeout);
这两个函数反映了一种,不行就算了的思想。
trylock不行就回退的思想有可能会引发活锁(live lock) 。 生活中也经常遇到两个人迎面走来, 双方都想给对方让路, 但是让的方向却不协调, 反而互相堵住的情况 。 活锁现象与这种场景有点类似。

线程1首先申请锁mutex_a后, 之后尝试申请mutex_b, 失败以后, 释放mutex_a进入下一轮循环, 同时线程2会因为尝试申请mutex_a失败,而释放mutex_b, 如果两个线程恰好一直保持这种节奏, 就可能在很长的时间内两者都一次次地擦肩而过。 当然这毕竟不是死锁, 终究会有一个线程同时持有两把锁而结束这种情况。 尽管如此, 活锁的确会降低性能。
6.8.5死锁调试
查看多个线程堆栈:thread apply all bt跳转到线程中:t 线程号查看具体的调用堆栈:f 堆栈号直接从pid号用gdb调试:gdb attach pid#include #include #include #include #include #define NUMBER 2pthread_mutex_t mutex1;//定义互斥锁pthread_mutex_t mutex2;void *ThreadWork1(void *arg){ int *p = (int*)arg; pthread_mutex_lock(&mutex1); sleep(2); pthread_mutex_lock(&mutex2); pthread_mutex_unlock(&mutex2); pthread_mutex_unlock(&mutex1); return NULL;}void *ThreadWork2(void *arg){ int *p = (int*)arg; pthread_mutex_lock(&mutex2); sleep(2); pthread_mutex_lock(&mutex1); pthread_mutex_unlock(&mutex1); pthread_mutex_unlock(&mutex2); return NULL;}int main(){ pthread_t tid[NUMBER]; pthread_mutex_init(&mutex1,NULL);//互斥锁初始化 pthread_mutex_init(&mutex2,NULL);//互斥锁初始化 int i = 0; int ret = pthread_create(&tid[0],NULL,ThreadWork1,(void*)&i); if(ret != 0) { perror("pthread_create"); return -1; } ret = pthread_create(&tid[1],NULL,ThreadWork2,(void*)&i); if(ret != 0) { perror("pthread_create"); return -1; } //pthread_join(tid,NULL);//线程等待 //pthread_join(tid,NULL);//线程等待 //pthread_detach(tid);//线程分离 pthread_join(tid[0],NULL); pthread_join(tid[1],NULL); pthread_mutex_destroy(&mutex1);//销毁互斥锁 pthread_mutex_destroy(&mutex2);//销毁互斥锁 while(1) { printf("i am main work threadn"); sleep(1); } return 0;}