读写锁在对资源进行保护的同时,还能区分想要读取资源值的线程(读取者线程)和想要更新资源的线程(写入者线程)。对于读取者线程,读写锁会允许他们并发的执行。当有写入者线程在占有资源时,读写锁会让其它写入者线程和读取者线程等待。因此用读写锁来解决读者写者问题会使代码非常清晰和简洁。SRWLock从visualstudio2005开始你可以使用SRWLock,和CRITICAL_SECTION(关键段)差不过的功能,不同的是由程序员控制读写线程,如果是读线程,可以同时读取,如果是写线程,则其他线程挂起,写完后马上就可以读取首先,需要一个SRWLOCK结构,然后调用InitializeSRWLock(PSWRLOCKsrwLock)函数初始化这个结构.12345678910SRWLOCKsrw;InitializeSRWLock(&srw);一旦初始化完成,就可以对写入线程调用AcquireSRWLockExclusive()函数和ReleaseSRWLockExclusive()函数AcquireSRWLockExclusive(&srw);//...写入数据,写入东西的时候该线程独占,其他任何线程不可进入ReleaseSRWLockExclusive(&srw);对于只读线程可以调用AcquireSRWLockShared()函数和ReleaseSRWLockShared()函数,如下AcquireSRWLockShared(&srw);//..读取数据,如果这时没有写入数据则多个读取线程可以进行ReleaseSRWLockShared)&srw);Slim读/写锁SRWLock的目的和关键段相同:对一个资源进行保护,不让其它线程访问它。但是,与关键段不同的是,SRWLock允许我们区分哪些想要读取资源的值的线程(读取者线程)和想要更新资源的值的线程(写入者线程)。让所有的读取者线程在同一时刻访问共享资源应该是可行的,这是因为仅仅读取资源的值并不存在破坏数据的风险。只有当写入者线程想要对资源进行更新的时候才需要进行同步。在这种情况下,写入者线程想要对资源进行更新的时候才需要进行同步。在这种情况下,写入者线程应该独占对资源的访问权:任何其它线程,无论是读取者线程还是写入者线程,都不允许访问资源。这就是SRWLock提供的全部功能。首先,我们需要分配一个SRWLOCK结构并用InitializeSRWLock函数对它进行初始化:VOIDInitializeSRWLock(PSRWLOCKSRWLock);一旦SRWLock初始化完成之后,写入者线程就可以调用AcquireSRWLockExclusive,将SRWLOCK对象的地址作为参数传入,以尝试获得对被保护资源的独占访问权。VOIDAcquireSRWLockExclusive(PSRWLOCKSRWLock);完成对资源的更新之后,应该调用ReleaseSRWLockExclusice,并将SRWLOCK对象的地址作为参数传入,这样就解除了对资源的锁定。VOIDReleaseSRWLockExclusive(PSRWLOCKSRWLock);对读取者线程来说,同样有两个步骤,单调用的是下面两个新的函数:VOIDAcquireSRWLockShared(PSRWLOCKSRWLock);VOIDReleaseSRWLockShared(PSRWLOCKSRWLock);不存在用来删除或销毁SRWLOCK的函数,系统会自动执行清理工作。与关键段相比,SRWLock缺乏下面两个特性:1)不存在TryEnter(Shared/Exclusive)SRWLock之类的函数:如果锁已经被占用,那么调用AcquireSRWLock(Shared/Exclusive)会阻塞调用线程。2)不能递归地调用SRWLOCK。也就是说,一个线程不能为了多次写入资源而多次锁定资源,然后再多次调用ReleaseSRWLock*来释放对资源的锁定。总结,如果希望在应用程序中得到最佳性能,那么首先应该尝试不要共享数据,然后依次使用volatile读取,volatile写入,InterlockedAPI,SRWLock以及关键段。当且仅当所有这些都不能满足要求的时候,再使用内核对象。因为每次等待和释放内核对象都需要在用户模式和内核模式之间切换,这种切换的CPU开销非常大。具体参考代码:1234//读者与写者问题继读写锁SRWLock#includestdio.h#includeprocess.h#includewindows.h567891011121314151617181920212223242526//设置控制台输出颜色BOOLSetConsoleColor(WORDwAttributes){HANDLEhConsole=GetStdHandle(STD_OUTPUT_HANDLE);if(hConsole==INVALID_HANDLE_VALUE)returnFALSE;returnSetConsoleTextAttribute(hConsole,wAttributes);}constintREADER_NUM=5;//读者个数//关键段和事件CRITICAL_SECTIONg_cs;SRWLOCKg_srwLock;//读者线程输出函数(变参函数的实现)voidReaderPrintf(char*pszFormat,...){va_listpArgList;va_start(pArgList,pszFormat);EnterCriticalSection(&g_cs);vfprintf(stdout,pszFormat,pArgList);LeaveCriticalSection(&g_cs);va_end(pArgList);}27282930313233343536373839404142434445464748//读者线程函数unsignedint__stdcallReaderThreadFun(PVOIDpM){ReaderPrintf(编号为%d的读者进入等待中...\n,GetCurrentThreadId());//读者申请读取文件AcquireSRWLockShared(&g_srwLock);//读取文件ReaderPrintf(编号为%d的读者开始读取文件...\n,GetCurrentThreadId());Sleep(rand()%100);ReaderPrintf(编号为%d的读者结束读取文件\n,GetCurrentThreadId());//读者结束读取文件ReleaseSRWLockShared(&g_srwLock);return0;}//写者线程输出函数voidWriterPrintf(char*pszStr){EnterCriticalSection(&g_cs);SetConsoleColor(FOREGROUND_GREEN);printf(%s\n,pszStr);SetConsoleColor(FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);LeaveCriticalSection(&g_cs);49505152535455565758596061626364656667686970}//写者线程函数unsignedint__stdcallWriterThreadFun(PVOIDpM){WriterPrintf(写者线程进入等待中...);//写者申请写文件AcquireSRWLockExclusive(&g_srwLock);//写文件WriterPrintf(写者开始写文件.....);Sleep(rand()%100);WriterPrintf(写者结束写文件);//标记写者结束写文件ReleaseSRWLockExclusive(&g_srwLock);return0;}intmain(){printf(读者写者问题继读写锁SRWLock\n);printf(--byMoreWindows()--\n\n);//初始化读写锁和关键段InitializeCriticalSection(&g_cs);InitializeSRWLock(&g_srwLock);717273747576777879808182838485868788HANDLEhThread[READER_NUM+1];inti;//先启动二个读者线程for(i=1;i=2;i++)hThread[i]=(HANDLE)_beginthreadex(NULL,0,ReaderThreadFun,NULL,0,NULL);//启动写者线程hThread[0]=(HANDLE)_beginthreadex(NULL,0,WriterThreadFun,NULL,0,NULL);Sleep(50);//最后启动其它读者结程for(;i=READER_NUM;i++)hThread[i]=(HANDLE)_beginthreadex(NULL,0,ReaderThreadFun,NULL,0,NULL);WaitForMultipleObjects(READER_NUM+1,hThread,TRUE,INFINITE);for(i=0;iREADER_NUM+1;i++)CloseHandle(hThread[i]);//销毁关键段DeleteCriticalSection(&g_cs);return0;}