#include <windows.h>
#include <iostream.h>
DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);
//两个全局变量,属于应用程序进程的,应该可以说明线程能够访问进程的所有内存,也能访问在这个进程
//中的所有其他线程的堆栈
int index=0;
int tickets=100;
void main()
{
HANDLE hThread1;
HANDLE hThread2;
//创建线程
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
Sleep(4000);
}
DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
while (TRUE)
{
if (tickets>0)
{
cout<<"thread1 sells ticket:"<<tickets--<<endl;
}
else
{
break;
}
}
return 0;
}
DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
while (TRUE)
{
if (tickets>0)
{
cout<<"thread2 sells ticket:"<<tickets--<<endl;
}
else
{
break;
}
}
return 0;
}
整个多线程可以这样理解,一段程序运行,得到一个应用程序,这个应用程序包含一个进程,而这个进程中包括三个线程,其中main是主线程,有主线程生成两个线程thread1,thread2,这三个线程之间的运行是通过时间片轮转的方式运行的,每个线程有一个时间片运行,当他所拥有的时间片运行完以后,就换成其他线程运行,而线程之间,以及线程与进程之间的数据是可以相互访问的,这样就可以进行线程同步了。
在main函数中采用了sleep,保证在票卖完100张,如果去掉这一句或者把4000换成非常小的数就可能发现票没有卖完,当然了,现在的电脑速度很快,尤其是多核电脑速度也是有可能在不sleep得情况下运行完成的。
也可以将sleep换成一个while循环,这样也可以运行,主线程main也是运行的,会占用CPU的时间,影响程序执行效率。
这里存在着一个很隐蔽的问题,考虑一种特殊的情况,当tickets=1时,thread1或thread2执行到if语句,if判断完成后它所拥有的时间片刚好执行完成,这时系统选择另一个线程执行,将票数减一,线程返回后,回到之前的线程,这时已经不需要再判断tickets了,就会输出0了。为了避免这种情况,在两个线程if块中都加入一句sleep(1),当线程判断完if后,就将该进程休眠,执行另一个进程,当1毫秒到了以后返回执行。也就是相当于将判断和减一分离开来。
关于sleep,Causes the currently executing thread to sleep (cease execution) for the specified number of milliseconds plus the specified number of nanoseconds. The thread does not lose ownership of any monitors.