诡异的线程同步问题(高手进)
程序如下:
total += 1;的汇编码为:
线程在第3行汇编码之前切换就会导致total的值不准确。
比如第一个线程在total为0时执行完第1行汇编码,然后切换到线程2。
等待线程2执行完之后再将eax的值写入到total的内存区,total的值将变成1。
线程1执行完之后total的值为M。
按我的分析total的范围应该是[M,2M]的闭区间。
可统计的结果显示min有可能小于M,尤其的是M越大越明显,很诡异吧!!!
而且我也测试过,每次都是两个线程结束后统计的min和max,所以找不到原因了,求解答。。。
#include <iostream>
#include <process.h>
#include <Windows.h>
using namespace std;
long total = 0;
const int M = 100000;
unsigned __stdcall ThreadProc(void*)
{
for(long i = 1; i <= M; i++)
total += 1;
return 0;
}
int main(int argc, char* argv[])
{
const int N = 10000;
HANDLE h[2];
int min = 0;
int max = 0;
//统计N次total的最小和最大值
for(int i = 0; i < N; i++)
{
total = 0;
h[0] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, 0, NULL);
h[1] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, 0, NULL);
//等待两个线程都结束
WaitForMultipleObjects(2, h, TRUE, INFINITE);
CloseHandle(h[0]);
CloseHandle(h[1]);
if(min == 0)
min = total;
if(total < min)
{
min = total;
}
if(total > max)
{
max = total;
}
}
cout << "(" << min << "," << max << ")";
return 0;
}
total += 1;的汇编码为:
1, mov eax,dword ptr [total (0E69148h)]
2, add eax,1
3, mov dword ptr [total (0E69148h)],eax
线程在第3行汇编码之前切换就会导致total的值不准确。
比如第一个线程在total为0时执行完第1行汇编码,然后切换到线程2。
等待线程2执行完之后再将eax的值写入到total的内存区,total的值将变成1。
线程1执行完之后total的值为M。
按我的分析total的范围应该是[M,2M]的闭区间。
可统计的结果显示min有可能小于M,尤其的是M越大越明显,很诡异吧!!!
而且我也测试过,每次都是两个线程结束后统计的min和max,所以找不到原因了,求解答。。。
...全文
相关推荐
浅谈SpringMVC HandlerInterceptor诡异问题排查
本文将主要介绍如何排查SpringMVC HandlerInterceptor中的诡异问题,解决问题的思路和方法,并对相关的源代码进行分析和解释。
【高并发】一文解密诡异并发问题的第一个幕后黑手——可见性问题
"高并发、CPU缓存、变量、可见性、并发、线程、缓存"在并发编程中,尤其是在多线程环境下,一个重要的挑战是确保数据的正确同步和可见性。可见性问题通常是由CPU缓存机制引起的,它是并发编程中诡异问题
一次诡异的full gc查找问题全过程
但是,我们怀疑是 client.Log(logEntries) 这个方法本身不是线程安全的。于是,我们把线程同步块锁在了 client.Log(logEntries) 这个代码块上。
java web开发过程中出现的一些诡异问题(2)
为避免此类问题,确保在使用对象之前进行非空检查,并始终在声明后立即初始化对象。2. **线程安全问题** Java Web应用通常涉及多线程环境,如果不正确地管理共享资源,可能会出现线程安全问题。
诡异通道Chrome插件-crx插件
诡异通道Chrome插件正是为了解决这个问题而生,它优化了网络连接路径,使得用户能够更快地浏览全球各地的网页内容。首先,我们需要了解什么是CRX插件。


