接着昨天的文章
- 先回答上篇文章的问题:什么原因造成数据混乱?
首先计算靠的是 CPU,而CPU 的寄存器只能存储极少的数据,时时需要和内存交换。
这时 CPU 通过内存地址取值的时候,如果是操作的是共享资源(例如:全局变量),且进行多线程操作,如果某个线程的操作完后,还没有马上将数据放回内存,就失去了 CPU,那么在其他线程操作这个共享数据的时候,使用的还是旧值,数据自然就发生了混乱。
简单点一句话概括:你操作得太快了,其他人还没拿到最新的值,就去干活了。
- 如何解决这个问题呢?
最主流的方法就是在操作共享数据前后添加 mutex 锁 (互斥锁)。
互斥锁
作用:
它用于防止多个线程同时访问共享资源。通过一种简单的加锁的方法来控制共享资源的访问, 互斥锁只有两种状态, 即lock和unlock
特点:
- 原子性: 把一个互斥量锁定为一个原子操作,保证了如果一个线程锁定了一个互斥量,没有其他线程在同一时间可以成功锁定这个互斥量
- 唯一性:如果一个线程锁定了一个互斥量,在它解除锁定之前,没有其他线程可以锁定这个互斥量
- 非繁忙等待: 如果一个线程已经锁定了一个互斥量,第二个线程又试图去锁定这个互斥量,则第二个线程将被挂起(不占用任何 cpu 资源),直到第一个线程解除对这个互斥量的锁定为止,第二个线程则被唤醒并继续执行,同时锁定这个互斥量。
pthread_mutex_init
简述:初始化一个互斥锁,只要你调用了,就一定要初始化!
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *attr);
pthread_mutex_lock
简述:对互斥锁进行 lock,如果对已经上锁的资源进行调用,调用者会一直处于阻塞状态
int pthread_mutex_lock(pthread_mutex_t *mutex);
pthread_mutex_unlock
简述:有 lock 就有它与 lock 对应,对互斥锁进行 unlock。
int pthread_mutex_unlock(pthread_mutex_t *mutex);
pthread_mutex_destroy
简述:用完了锁记得销毁哦~ 为了释放资源
int pthread_mutex_destroy(pthread_mutex_t *mutex);
这四个足以应付大部分的情况了。
pthread_mutex_trylock
简述:调用该函数时,若互斥锁未加锁,则上锁,返回 0,如果互斥锁已加锁,则函数直接返回失败 EBUSY
int pthread_mutex_trylock(pthread_mutex_t *mutex);
改进昨天的代码
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <windows.h>//使用Sleep的头
int g_number = 0;
#define MAX_COUNT 10000
pthread_mutex_t mut;
void *counter3(void* args) {
int i = 1;
while (i <= MAX_COUNT / 4) {
pthread_mutex_lock(&mut);
g_number++;
pthread_mutex_unlock(&mut);
printf("hi,i am pthread 3, my g_number is [%d]\n", g_number);
Sleep(1);// 单位ms
i++;
}
}
void *counter4(void* args) {
int j = 1;
while (j <= MAX_COUNT / 4) {
pthread_mutex_lock(&mut);
g_number++;
pthread_mutex_unlock(&mut);
printf("hi,i am pthread 4, my g_number is [%d]\n", g_number);
Sleep(1);
j++;
}
}
int main() {
pthread_mutex_init(&mut, NULL);
pthread_t t3;
pthread_t t4;
pthread_create(&t3, NULL, counter3, NULL);
pthread_create(&t4, NULL, counter4, NULL);
pthread_join(t3, NULL);
pthread_join(t4, NULL);
return 0;
}
5000,程序正常!
修改了下代码规范问题,代码格式很重要!
https://zhuanlan.zhihu.com/p/97512154