当前位置: 首页 > news >正文

Linux学习记录--多线程共享变量

多线程编程中的共享变量:从协作到冲突,再到秩序

一组并发线程运行在一个进程的上下文中,每个线程都有自己独立的线程上下文,包括线程ID、栈、栈指针、程序计数器、条件码和通用目的寄存器值。每个线程和其他线程一起共享进程上下文剩余部分。这包括整个用户虚拟地址空间,它是由只读文本、读/写数据、堆以及所有的共享库代码和数据区域组成的。线程也共享相同的打开文件的集合。


一、共享变量:线程之间的“公共黑板”

在多线程程序中,共享变量是最直接的通信方式。它就像一块公共黑板,每个线程都可以读、可以写,用来传递信息、协调工作。

我们来看一个简单但典型的例子


二、案例1:sharing.c——共享变量让线程“各取所需”

2.1 程序代码(简化)

char **ptr;  // 全局共享数组void* thread(void* vargp) {int myid = (int)(intptr_t)vargp;static int cnt = 0;printf("[%d]: %s (cnt=%d)\n", myid, ptr[myid], ++cnt);return NULL;
}int main() {pthread_t tid;char *messages[2] = {"Hello, I am Thread 1.","Hello, I am Thread 2."};ptr = messages;  // 共享指针for (int i = 0; i < 2; i++)pthread_create(&tid, NULL, thread, (void*)(intptr_t)i);pthread_exit(NULL);  // 主线程等待所有子线程结束
}

2.2 运行结果(某次)

一次运行结果

2.3 共享变量如何“协作”?

  • ptr全局指针,两个线程都能访问;
  • 每个线程根据 myid 读取自己的那一行字符串
  • cnt函数内静态变量,每个线程独立一份(不是共享的),用来记录自己被调用的次数。

这里没有冲突:线程只“读”共享数据,不“写”共享数据。


2.4 技术小亮点:整数也能“伪装”成指针

pthread_create(&tid, NULL, thread, (void*)(intptr_t)i);
  • pthread_create 只能传 void* 指针;
  • 但我们想传整数 i,怎么办?
  • (intptr_t)i 把整数“塞”进指针,避免了 malloc,简洁又安全。

小技巧:只传“值”,不传“地址”,避免访问已销毁的局部变量。


三、案例2:badcnt.c——共享变量“看似没问题”,却悄悄出错

多线程程序就像一间开放式厨房,多个厨师可以共享调料架(共享变量),一起做出更高效的晚餐。但共享并不意味着“随便用”,一旦有人同时往同一瓶盐里加盐,就可能出问题。

3.1 程序逻辑:两个线程一起数数

volatile long cnt = 0;  // 全局计数器void* thread(void* vargp) {long niters = *((long*)vargp);for (long i = 0; i < niters; i++)cnt++;  // 看似简单的加法return NULL;
}int main(int argc, char** argv) {long niters = atoi(argv[1]);pthread_t tid1, tid2;pthread_create(&tid1, NULL, thread, &niters);pthread_create(&tid2, NULL, thread, &niters);pthread_join(tid1, NULL);pthread_join(tid2, NULL);printf("Final cnt = %ld (expected %ld)\n", cnt, 2 * niters);return 0;
}

3.2 运行结果:不稳定!

在这里插入图片描述

3.3 问题出在哪?cnt++ 不是“一条指令”

cnt++ 在汇编层面是三步:

  1. cnt 到寄存器;
  2. 寄存器加 1;
  3. 写回内存。

两个线程可能同时读到同一个值,然后各自加 1,写回同一个结果。于是,有一次加法“丢失”了

时间线程1线程2内存中 cnt
t1读 cnt=1010
t2读 cnt=1010
t3寄存器=1110
t4寄存器=1110
t5写回 1111
t6写回 1111

期望是 12,结果是 11


3.4 小结:共享变量“读写”才危险

  • sharing.c只读共享,安全;
  • badcnt.c读写共享,出错;
  • 问题不在于“共享”,而在于同时写

四、从冲突到秩序:我们该怎么办?

我们已经看到:

  • 共享变量可以让线程高效协作
  • 但一旦涉及同时写,就可能悄悄出错
  • 错误不是“崩溃”,而是结果不对,更难发现。

那么,如何保证“写”操作不会互相打扰?

就像厨房里的盐罐,一次只能一个人用,我们需要一个“规则”。

这个规则,就是同步机制

在下一篇文章中,我们将介绍:

  • 信号量(semaphore)互斥锁(mutex)
  • 如何用信号量修复 badcnt.c
  • 如何把这种“规则”应用到更复杂的并发场景。

五、结语:共享变量不是“不能用”,而是“要会用”

场景是否安全原因
线程只读共享变量✅ 安全不修改数据,互不干扰
线程共享变量⚠️ 需同步可能“踩”到彼此的操作

共享变量就像公共厨房里的调料架:

  • 每个人都可以看;
  • 同时往同一瓶里加盐,就要排队;
  • 信号量,就是那张“一次只能一个人”的小纸条。

六、预告:下一篇《用信号量建立秩序:让多线程不再踩脚》

我们将:

  • 信号量修复 badcnt.c
  • 介绍二元信号量(互斥锁)和计数信号量
  • 带你一步步把“混乱”变成“秩序”。

如果本文对你有帮助,记得点赞 + 收藏 + 关注,第一时间获取下一篇更新!
欢迎留言交流你在多线程里踩过的坑~

http://www.dtcms.com/a/398517.html

相关文章:

  • 网站格式有哪些内容私人建设手机网站
  • 【Java后端】SpringBoot 常用工具类和工具方法汇总
  • leetcode hot100 中等难度 day03-刷题
  • Android | 使用 dumpsys alarm 验证自己应用使用的 Alarm 是否正确
  • React 展示Markdown内容
  • 营销型网站标准网页源码江西旺达建设工程有限公司网站
  • 南昌网站建设公司咨询交通局网站建设方案策划书
  • 阅读:Agent AI:Surveying the Horizons of Multimodal Interaction (2.2.1-2.2.3)
  • 提升网站建设品质福建省建设厅网站林瑞良
  • 阿里云网站建设服务费会计科目农产品网站建设投标书
  • 「企业模糊查询搜索api接口」详细介绍及调用使用方法
  • 【一天一个Web3概念】深入解析Web3空投:类型、参与策略与安全指南
  • JS逆向-Sign签名绕过技术算法可逆替换库模拟发包堆栈定位特征搜索安全影响
  • 网站一起做网店美工做兼职在那个网站
  • CI/CD Pipeline:完整指南
  • go引入自定义mod
  • 做网站需要多长时间iis 配置网站详解
  • 【Android】解决安卓在隐藏系统栏后usb鼠标被隐藏的问题
  • 公司企业网站免费建设长沙市天心区建设局网站
  • VS Code 格式化配置优先级与作用机制(包含ESLint)
  • IP地址的分类方法
  • 【halcon】新版 HALCON 中 `flush_graphic` 的正确打开方式
  • 数据科学-损失函数
  • Linux中mysql修改系统时间为北京时间,并修改成24h制,第275章
  • 网络通讯篇防火墙组策略入站和出站规则单层双层C2正反向上线解决方案
  • 【力扣LeetCode】 1413_逐步求和得到正数的最小值
  • 给别人做网站赚钱吗wordpress邮件找客户端
  • 有没有做logo的网站网站开发常去的论坛
  • todesk连接Mac设备时卡在100%(手机、平板连接时卡在75%)
  • ETF网格策略的呼吸机制基于市场热度的动态间距调控