c++ - 以下代码在并发情况下的可能结果是什么?
问题描述
我看到一个面试问题如下:以下代码结果的可能范围是多少:
void ThreadProc(int& sum)
{
for (int i = 1; i <= 50; i++)
{
sum += 1;
}
}
int main()
{
int sum = 0;
thread t1(ThreadProc, std::ref(sum));
thread t2(ThreadProc, std::ref(sum));
t1.join();
t2.join();
cout << sum << '\n';
return 0;
}
给出的答案是[50,100]。但是,我认为应该是[2,100]。如果给定序列如下,sum
将是2。
- 线程
t1
获取 cpu,并将初始值加载sum=0
到缓存中(假设缓存的总和是c1
,它的值是0
现在)。 - 线程
t2
获取cpu,并增加(49次),现在总和为49。 - 线程
t1
获取 cpu 和计算sum = c1 + 1
,现在sum
是1
. - 线程
t2
获取cpu,并加载sum
(=1
)并计算sum + 1
并缓存结果(c1
现在2
)。在c1
被写入变量sum
之前t1
,t2
抢占cpu。 - 线程
t2
获取cpu,并增加(1倍)[现在sum
将是x
(值无所谓)],然后thread t2
完成。 线程
t1
获取cpu,并将缓存结果写入c1
sum,现在sum
是2
.我对吗?
解决方案
此代码会导致未定义的行为,因为sum
是从两个不同的线程修改的,没有任何并发保护。这在 C++ 标准中称为数据竞争。
因此,任何行为都是可能的(包括但不限于您提到的所有情况)。
推荐阅读
- node.js - 错误:默认 Firebase 应用不存在
- python - 对照某一行检查变量。Python
- java - 我可以在我的 Android 应用中的 NavigationView 项目中使用 Google 登录吗?
- ios - Swift iOS -Second UIWindow 有时会从错误的坐标动画
- python - 无法在 Mac OS High Sierra 版本 10.13.5 上安装 virtualenv
- angular - 在 Azure 中部署 Angular 应用并使用 VSTS 配置 CI/CD
- esp8266 - ESP8266 没有唤醒?
- php - 一次查询获取视频和类别
- c# - 如何修改代码,以便在方法 getProductTransaction 中返回交易列表而不是单个交易
- ios - Xcode 9.0 和 Firebase 5.0.4 上的位码版本无效