详解linux多线程——互斥锁、条件变量、读写锁、自旋锁、信号量

x一、互斥锁(同步)
  在多任务操作系统中 , 同时运行的多个任务可能都需要使用同一种资源 。这个过程有点类似于 , 公司部门里 , 我在使用着打印机打印东西的同时(还没有打印完) , 别人刚好也在此刻使用打印机打印东西 , 如果不做任何处理的话 , 打印出来的东西肯定是错乱的 。
  在线程里也有这么一把锁——互斥锁(mutex) , 互斥锁是一种简单的加锁的方法来控制对共享资源的访问 , 互斥锁只有两种状态,即上锁( lock )和解锁( unlock ) 。
【互斥锁的特点】:
1. 原子性:把一个互斥量锁定为一个原子操作 , 这意味着操作系统(或pthread函数库)保证了如果一个线程锁定了一个互斥量 , 没有其他线程在同一时间可以成功锁定这个互斥量;
2. 唯一性:如果一个线程锁定了一个互斥量 , 在它解除锁定之前 , 没有其他线程可以锁定这个互斥量;
3. 非繁忙等待:如果一个线程已经锁定了一个互斥量 , 第二个线程又试图去锁定这个互斥量 , 则第二个线程将被挂起(不占用任何cpu资源) , 直到第一个线程解除对这个互斥量的锁定为止 , 第二个线程则被唤醒并继续执行 , 同时锁定这个互斥量 。
【互斥锁的操作流程如下】:
1. 在访问共享资源后临界区域前 , 对互斥锁进行加锁;
2. 在访问完成后释放互斥锁导上的锁 。在访问完成后释放互斥锁导上的锁;
3. 对互斥锁进行加锁后 , 任何其他试图再次对互斥锁加锁的线程将会被阻塞 , 直到锁被释放 。对互斥锁进行加锁后 , 任何其他试图再次对互斥锁加锁的线程将会被阻塞 , 直到锁被释放 。
#include <pthread.h>#include <time.h>// 初始化一个互斥锁 。int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *attr);// 对互斥锁上锁 , 若互斥锁已经上锁 , 则调用者一直阻塞 , // 直到互斥锁解锁后再上锁 。int pthread_mutex_lock(pthread_mutex_t *mutex);// 调用该函数时 , 若互斥锁未加锁 , 则上锁 , 返回 0;// 若互斥锁已加锁 , 则函数直接返回失败 , 即 EBUSY 。int pthread_mutex_trylock(pthread_mutex_t *mutex);// 当线程试图获取一个已加锁的互斥量时 , pthread_mutex_timedlock 互斥量// 原语允许绑定线程阻塞时间 。即非阻塞加锁互斥量 。int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,const struct timespec *restrict abs_timeout);// 对指定的互斥锁解锁 。int pthread_mutex_unlock(pthread_mutex_t *mutex);// 销毁指定的一个互斥锁 。互斥锁在使用完毕后 , // 必须要对互斥锁进行销毁 , 以释放资源 。int pthread_mutex_destroy(pthread_mutex_t *mutex);【Demo】(阻塞模式):
//使用互斥量解决多线程抢占资源的问题#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <pthread.h>#include <string.h> char* buf[5]; //字符指针数组全局变量int pos; //用于指定上面数组的下标 //1.定义互斥量pthread_mutex_t mutex; void *task(void *p){//3.使用互斥量进行加锁pthread_mutex_lock(&mutex);buf[pos] = (char *)p;sleep(1);pos++;//4.使用互斥量进行解锁pthread_mutex_unlock(&mutex);} int main(void){//2.初始化互斥量, 默认属性pthread_mutex_init(&mutex, NULL);//1.启动一个线程 向数组中存储内容pthread_t tid, tid2;pthread_create(&tid, NULL, task, (void *)"zhangfei");pthread_create(&tid2, NULL, task, (void *)"guanyu");//2.主线程进程等待,并且打印最终的结果pthread_join(tid, NULL);pthread_join(tid2, NULL);//5.销毁互斥量pthread_mutex_destroy(&mutex);int i = 0;printf("字符指针数组中的内容是:");for(i = 0; i < pos; ++i){printf("%s ", buf[i]);}printf("n");return 0;}【Demo】(非阻塞模式):
#include <stdio.h>#include <pthread.h>#include <time.h>#include <string.h> int main (void){int err;struct timespec tout;struct tm *tmp;char buf[64];pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_lock (&lock);printf ("mutex is lockedn");clock_gettime (CLOCK_REALTIME, &tout);tmp = localtime (&tout.tv_sec);strftime (buf, sizeof (buf), "%r", tmp);printf ("current time is %sn", buf);tout.tv_sec += 10;err = pthread_mutex_timedlock (&lock, &tout);clock_gettime (CLOCK_REALTIME, &tout);tmp = localtime (&tout.tv_sec);strftime (buf, sizeof (buf), "%r", tmp);printf ("the time is now %sn", buf);if (err == 0)printf ("mutex locked againn");elseprintf ("can`t lock mutex again:%sn", strerror (err));return 0;}


推荐阅读