全局变量的最终值,该变量正在通过两个线程进行增量
Final value of a global variable which is being incremented via two threads
我遇到了这个问题:
给定两个线程和一个全局变量
var
,两个线程运行 相同的代码(C/C 代码):for(int i=0; i<20; i++) { var++; }
线程末端的
var
的可能值是多少 执行?
如果每个线程递增var
"正确" - 我猜最大值将为40。
但是最低值呢?增量操作如何实现和实际完成?
注意:有目的的增量操作没有锁定(任何类型的)(当然,正确的方法是锁定它 - 问题是出于教育目的)。
如果 var
是不是原子类型,则行为是 nespined 。因此,关于可能最终值的范围的问题是不适合的。
如果 var
是原子类型,则最终结果将是好像没有同时运行线程。
如果您不进行任何锁定,则var++
不是原子,即写入和变量的读取可以被另一个线程中断。这意味着这两个线程都可能读取相同的VAR值并同时读取它。
最坏的情况这两个线程完全"同步",这些线程完全同时读写和编写VAR,因此var
的最小终点为20。
更新:显然,这些数据竞赛中可能的结果无法保证,请参见下面的bathsheba答案,他提到的本文。
更新2 :我很好奇在现实世界中,我们是否会在下面看到值20。测试设置(详细信息:请参阅此GIST)
- 全局
int var
。用long
和long long
测试,没有任何区别 - 两个
pthread
S进行20'000倍var++
- 可执行文件启动了1000次,最小的值
预期的结果将在20'000到40'000之间:
| Computer | clang | clang -O3 | gcc | gcc -O0 | gcc -O2 |
|-----------------------------------------------|-------|-----------|-------|---------|---------|
| Linux, ThinkPad, x86_64, Intel I7, 4 cores | 19402 | 20000 | 18760 | 16913 | 20000 |
| Linux, Raspberry 3, ARMv7, 4 cores | 19587 | 20000 | 19569 | 19904 | 20000 |
| OSX, Intel i5, 4 cores | 17609 | 20000 | 17206 | 18049 | 20000 |
| Linux, EC2 t2.2xlarge, Intel Xeon E5, 8 cores | 19707 | 20000 | 19744 | 19881 | 40000 |
看起来很有趣的东西:
- 是的,它可以降至20'000以下,因此"不保证"主张不仅在理论上
- 随着编译器的优化高于一定级别,行为看起来更可预测
- 奇怪的是,在具有8个内核的EC2上,
gcc -O2
的最小值为40'000。
相关文章:
- 在两个线程上读/写 64 位,无互斥/锁定/原子
- 如果两个线程相互依赖,则 cpp 线程连接应使用连接导致死锁
- 两个线程一个使用流 Api,另一个线程创建文件失败并出现错误ERROR_SHARING_VIOLATION
- 简单使用 std::atomic 在两个线程之间共享数据
- 如何使用 pthreads 以正确的方式设置两个线程之一的优先级
- 曼德布洛特 从一个线程被反复使用变为两个线程
- C++ 两个线程,共享几个整数变量
- 如何正确同步这两个线程?
- 两个线程尝试将一些数据读/写到数据库中表的同一行中
- 两个线程的公共资源 - 同步足够吗?
- 如果两个线程调用同一个函数,但函数中的所有变量都是局部变量,我还需要担心线程之间共享数据吗?
- 当两个线程同时尝试在同一静音上尝试try_lock()时会发生什么
- C 带有两个线程的boost async_read vs
- 使用 Poco:Condition 唤醒两个线程
- C 两个线程一个用于输入,一个用于输出
- 将两个线程同步到同一个计时器
- 全局变量的最终值,该变量正在通过两个线程进行增量
- C++中两个线程的互斥体
- Qthread char阵列在两个线程之间传递后被摧毁
- 如何使用CPP中使用一个对象运行同一类的两个线程