线程的一个小问题
#include <windows.h>
#include <iostream.h>
DWORD WINAPI Fun1Proc(LPVOID lpParameter);
void main()
{
HANDLE hThread1;
hThread1 = CreateThread(NULL, 0, Fun1Proc, NULL, 0, NULL);
CloseHandle(hThread1);
cout < < "main thread is runing " < < endl;//语句1
Sleep(100);
}
DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
cout < < "thread1 is running " < < endl; //语句2
return 0;
}
这段代码多次运行发现
有时先打印语句1,有时先打印语句2
这两种情况程序运行的顺序是怎么样的?为什么会出现先打印语句二的情况
[解决办法]
(1)C++标准库并没有对并发访问进行内部互斥,你这里两个线程都使用了同一个标准库中的全局对象:cout。而且对它的并发访问没加任何互斥措施,这就完全有可能cout正在用它的operator < <为一个线程输出的时候,却被另一个线程打断,于是cout的内部状态遭到破坏,导致下次进程切换回来之后,它可能不知道自己已经把上次的打好了,于是就又打了一遍。
比这更可怕的例子也有,比如,你让两个线程同时操作一个链表,却不加任何互斥,那么当线程1从链表上拆除一个结点时,这时被线程2打断,线程2要从同一个位置插入一个结点……试想一下,除了一片混乱,你还能得到什么?:)
所以,多个线程操作同一个共享变量,一定要处理好同步互斥,不能使数据遭破坏,更不能让死锁发生。
(2)第二种比较简单,可能是main刚创建好那个线程,就被CPU调度下台了,然后新创建的线程上台运行,先行打出了它要打印的内容。
(3)第三种是main创建好了那个线程,结果自己的时间还没结束,只好接着往下执行,没想到后面没啥事情了,于是主线程退出,子线程没来得及做啥事也被迫退出。
最后,别忘了程序运行时执行的都是目标代码,而不是源代码,因此线程切换显然不一定发在一整行代码结束时。像这种简单的C++语句:
i += 2;
一般会被编译成两到三条机器执令,而任何一条指令执行完都可能被打断,所以,对于在多线程环境中共享变量,如果不处理好同步互斥,连i += 2这么简单的语句都会出错。更不用说cout < <了。。