一、进程线程间的互斥相关背景概念
临界资源:多线程执行流共享的资源就叫做临界资源。 临界区:每个线程内部,访问临界资源的代码,就叫做临界区。 互斥:用来保护临界区,任何时刻,互斥保证有且只有一个执行流进入临界区,访问临界资源,进而对临界资源起作用。当多个执行流向同一个共享资源做写入并且没有加保护,数据会发生写入错乱、覆盖等问题时就叫做数据写入不一致。(这也是多线程代码一定会面临的问题,因为多线程大部分资源都是共享的) 原子性(后面讨论如何实现):不会被任何调度机制打断的操作,该操作只有两态,要么完成,要么未完成。(原子性在多线程场景中并不是一种特性,而是一种结果,正是有了互斥的存在,故而有了访问资源的原子性)
补充:
- 互斥保护资源的本质是把多线程访问资源由并发执行转化为串行执行,所以互斥是可能会降低程序运行效率的。
- 多线程共享资源不会发生数据不一致问题,多线程并发访问共享资源才会发生数据不一致问题。所以多线程并不是所有共享资源都需要被保护,被访问的共享资源才需要被保护。
二、互斥量 mutex
为了实现互斥,所以需要引入一种新的数据类型:互斥量(互斥锁),它是完成互斥保护的数据对象和配套的方法。
我们看下面这个多线程并发访问一个全局变量的代码,它是模拟的一个抢票逻辑,每一个线程代表一个用户:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
int ticket = 100;
void* route(void* arg) {
char* id = (char*)arg;
while(1) {
if(ticket > 0) {
usleep(1000); // 模拟漫长的业务的过程,期间可能有很多个线程会进入该代码段
printf("%s sells ticket:%d\n", id, ticket);
ticket--;
} else {
break;
}
}
return (void*)0;
}
int main {
t1, t2, t3, t4;
pthread_create(&t1, , route, (*));
pthread_create(&t2, , route, (*));
pthread_create(&t3, , route, (*));
pthread_create(&t4, , route, (*));
pthread_join(t1, );
pthread_join(t2, );
pthread_join(t3, );
pthread_join(t4, );
}





