因为进程/线程间同步的方法比较多,每种方法都有不同的用途:这节中会讲通过临界区,互斥量,信号灯,事件来进行同步。
由于进程/线程间的操作是并行进行的,所以就产生了一个数据的问题同步,我们先看一段代码:
int iCounter=0;//全局变量
DOWRD threadA(void* pD)
{
for(int i=0;i<100;i++)
{
int iCopy=iCounter;
//Sleep(1000);
iCopy++;
//Sleep(1000);
iCounter=iCopy;
}
}
现在假设有两个线程threadA1和threadA2在同时运行那么运行结束后iCounter的值会是多少,是200吗?不是的,如果我们将Sleep(1000)前的注释去掉后我们会很容易明白这个问题,因为在iCounter的值被正确修改前它可能已经被其他的线程修改了。这个例子是一个将机器代码操作放大的例子,因为在CPU内部也会经历数据读/写的过程,而在线程执行的过程中线程可能被中断而让其他线程执行。变量iCounter在被第一个线程修改后,写回内存前如果它又被第二个线程读取,然后才被第一个线程写回,那么第二个线程读取的其实是错误的数据,这种情况就称为脏读(dirty read)。这个例子同样可以推广到对文件,资源的使用上。
那么要如何才能避免这一问题呢,假设我们在使用iCounter前向其他线程询问一下:有谁在用吗?如果没被使用则可以立即对该变量进行操作,否则等其他线程使用完后再使用,而且在自己得到该变量的控制权后其他线程将不能使用这一变量,直到自己也使用完并释放为止。经过修改的伪代码如下:
int iCounter=0;//全局变量
DOWRD threadA(void* pD)
{
for(int i=0;i<100;i++)
{
ask to lock iCounter
wait other thread release the lock
lock successful
|