简 述: 在 Linux 中,使用互斥量(互斥锁🔐) Mutex 来给保证多线程 ,在访问公共变量的时候能够 “串行” 代码。从而使得多线程正确的同步执行。关于多线程创建和使用可以参考前面几篇的文章,争取早日把 Linux 系统篇之 系统编程给发布完系列的教程。 PS:好几天没有接着学习 Linux 的系统函数和理论知识了。可能是前面几天有点忙了吧;时间流逝啊,总是这么得快,,,, 关于互斥锁的使用如下: 💻: 💻: 程序: 先写一个多线程程序,A 和 B 两个子线程一起数出输出到 100000;然后在没有锁🔐的情况下,每一线程轮流执行 10 毫秒,模拟时间片轮转切片。 代码程序: 这个代码还没有加锁,保护共享变量。完整代码如下; 结果分析: 下面截图里面,在 MacOS 10.14.6 和 Ubuntu 20.04 里面跑,都是正确的结果; [疑惑]可能是因为系统系统内核或者底层作了修改???又或者是数数的间隔过小,数的数字不多? 预判的结果是 实际数数的大小会比实际正确结果要小一点(原因是时间片轮转的原因),待日后挖坟考古?难道是系统比较新?所以连续出现几次都是最正确的结果。。。
[解答]没有出现内存来不及保存增加的数据,cpu 的时间片就被其他资源占去了,导致最后出现的小数有可能出现在大数的后面打印,这是一个概率问题;而 27-29 行和 42-44 行,是刻意增加寄存器和内存之间的数据交换操作次数,使得出现内存没来得及保存数据的现象的概率大一点。 如果在 Ubuntu 16.04 里面跑改程序,如果出现了最后一个数字比 100000 小一点,那么解释的可能如下: 其中会发现结果有点混乱。这是两个子线程互相操作同一个数据,时间片切换的时候,还新的数据还没有来得及保存进内存里面,就切换到了下一个线程中去了。 如果我们想使用互斥锁同步线程,那么所有线程,只要是有访问同一个共享公共变量的线程都要加锁。 创建一把互斥锁 对互斥锁进程初始化 init 使用互斥锁:每个子线程要访问公共变量的时候,都加上锁,使用完后就解锁 使用完毕,销毁互斥锁 将上面的例子改了改,然后在 A、B 两个子线程里面,使用互斥量(锁),会发现也会得到取其正确的结果。结果符合预期。 运行结果: 实际结果和预期结果一致。 欢迎 star 和 fork 这个系列的 linux 学习,附学习由浅入深的目录。
编程环境:
uos20
📎 gcc/g++ 8.3
📎 gdb8.0
MacOS 10.14
📎 gcc/g++ 9.2
📎 gdb8.3
背景铺垫:
#include <stdio.h> #include <unistd.h> #include <pthread.h> int g_num = 0; //在全局区域,共享 #define MAXNUMBER 100000 void* funA(void* arg); void* funB(void* arg); int main(int argc, char *argv[]) { pthread_t pthreadA = 0; pthread_t pthreadB = 0; pthread_create(&pthreadA, nullptr, funA, nullptr); //创建两个子线程 pthread_create(&pthreadB, nullptr, funB, nullptr); pthread_join(pthreadA, nullptr); //阻塞,回收资源 pthread_join(pthreadB, nullptr); return 0; } void* funA(void* arg) { for (int i = 0; g_num < MAXNUMBER; i++) { int a = g_num; //27-29行,增加寄存器和内存之间的数据交换操作,使得出现内存没来得及保存数据的现象的概率大一点 a++; g_num = a; printf("A thread id: %ld, num = %dn", pthread_self(), g_num); usleep(10); //沉睡 10 毫秒, 模拟时间片轮转,效果更明显 } return nullptr; } void* funB(void* arg) { for (int i = 0; g_num < MAXNUMBER; i++) { int b = g_num; b++; g_num = b; printf("B thread id: %ld, num = %dn", pthread_self(), g_num); usleep(10); //沉睡 10 毫秒, 模拟时间片轮转,效果更明显 } return nullptr; }
使用互斥量(锁) Mutex:
pthread_mutex_t *mutex
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
//若果没有上锁,就上锁;若果已经上锁,直接返回,不阻塞 int pthread_mutex_trylock(pthread_mutex_t *mutex); //若果没有上锁,就上锁;若果已经上锁,就阻塞该线程 int pthread_mutex_lock(pthread_mutex_t *mutex); //解锁 int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
改写例子,使用互斥量(锁)实例:
#include <stdio.h> #include <unistd.h> #include <pthread.h> int g_num = 0; //在全局区域,共享 #define MAXNUMBER 100000 pthread_mutex_t g_mutex; //创建全局的互斥锁 void* funA(void* arg); void* funB(void* arg); int main(int argc, char *argv[]) { pthread_mutex_init(&g_mutex, nullptr); //对锁进行初始化 pthread_t pthreadA = 0; pthread_t pthreadB = 0; pthread_create(&pthreadA, nullptr, funA, nullptr); //创建两个子线程 pthread_create(&pthreadB, nullptr, funB, nullptr); pthread_join(pthreadA, nullptr); //阻塞,回收资源 pthread_join(pthreadB, nullptr); pthread_mutex_destroy(&g_mutex); //释放互斥锁资源 return 0; } void* funA(void* arg) { for (int i = 0; g_num < MAXNUMBER; i++) { pthread_mutex_lock(&g_mutex); int a = g_num; a++; g_num = a; printf("A thread id: %ld, num = %dn", pthread_self(), g_num); pthread_mutex_unlock(&g_mutex); usleep(10); //沉睡 10 毫秒, 模拟时间片轮转,效果更明显 } return nullptr; } void* funB(void* arg) { for (int i = 0; g_num < MAXNUMBER; i++) { pthread_mutex_lock(&g_mutex); int b = g_num; b++; g_num = b; printf("B thread id: %ld, num = %dn", pthread_self(), g_num); pthread_mutex_unlock(&g_mutex); usleep(10); //沉睡 10 毫秒, 模拟时间片轮转,效果更明显 } return nullptr; }
下载地址:
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算