线程同步是一个很困扰大家的一个问题,在线程中有时需要必须的同步机制来控制程序的运行,但什么时候需要加同步机制,什么地方又不需要这些没必要的同步机制呢?在不需要同步的地方加上了同步机制只会降低程序的效率,所以不必要的地方就一定不要加上同步的代码。
我们首先要明白,线程在切换之间都做了些什么事情,首先我们要知道,在系统中全局变量是在全局空间分配的,而局部变量是在系统堆栈中分配的,大家注意了,这两点概念很重要的。操作系统会为我们的每一个线程保护寄存器和堆栈现场,也就是说在线程切换的时候操作系统会为我们的线程恢复原来的寄存器和堆栈现场的(懂些汇编可能更容易理解一些)。所以大家一定要明确,虽然多个线程执行的代码相同,但是他们的局部变量的值实际上也是不相同的,因为线程切换的时候操作系统会恢复他们原来的值,所以局部变量一般不需要同步。
void fun(int n1, int n2)
{
n1++;
n2++;
}
int n1 = 123;
int n2 = 444;
DWORD WINAPI _WorkerThreadProc(LPVOID lpParam)
{
fun(n1, n2);
return 0;
}
void CMy11Dlg::OnBnClickedOk()
{
for (int i =0; i<3; i++)
{
CreateThread(NULL, 0, _WorkerThreadProc, 0, 0, NULL);
}
Sleep(1000);
int nc = n1+n2;
}
对于上面的代码 用od反汇编后 堆栈地址图
在系统中全局变量是在全局空间分配的,而局部变量是在系统堆栈中分配的。
3次线程 系统堆栈中的地址分别为
线程1: 0x035afea8
线程2: 0x036afea8
线程3: 0x037afea8
可见每个线程都有 独立的 系统堆栈现场, 每个线程 局部变量都保存在独立的堆栈现场中,故而无需同步。