【win32多线程】数据的一致性问题,即多个线程读写数据问题
来源:互联网 发布:ipone5s安装不了软件 编辑:程序博客网 时间:2024/06/11 14:04
1.把锁定搬到更高的层次
void AddLineItems(List *pList)
{
Node node;
while()
{
getLineItem(&item);
AddHead(pList,&node);
}
}
void AddHead(List *pList,Node *pNode)
{
EnterCriticalSection(&pList->critical_sec);
pNode->next=pList->head;
pList->head=pNode;
LeaveCriticalSection(&pList->critical_sec);
}
搬到更高的层次
void AddLineItems(List *pList)
{
Node node;
EnterCriticalSection(&pList->critical_sec);
while()
{
getLineItem(&item);
AddHead(pList,&node);
}
LeaveCriticalSection(&pList->critical_sec);
}
void AddHead(List *pList,Node *pNode)
{
pNode->next=pList->head;
pList->head=pNode;
}
这样的模型有助于windows程序,因为其线程是事件驱动模式,而且常常返回到主消息循环中。
2.读写锁
排他锁看起来不错,但是它会强迫所有的存取操作都按照先后次序来,而多线程的好处也就流失了。这种情况下最好用单一线程。
为Reader锁定
Lock(ReaderMutex)
ReadCount=ReadCount+1;
if(ReadCount==0)
Unlock(DataSemaphore)
Unlock(ReaderMutex)
为Reader解除锁定
Lock(ReaderMutex)
ReadCount=ReadCount-1;
if(ReadCount==0)
Unlock(DataSemaphore)
Unlock(ReaderMutex)
为Writer锁定
Lock(DataSemaphore)
为Writer解除锁定
Unlock(DataSemaphore)
实现Reader/Writer的数据结构
ReadWrit.h
typedef struct _RWLock{ // Handle to a mutex that allows // a single reader at a time access // to the reader counter. HANDLEhMutex; // Handle to a semaphore that keeps // the data locked for either the // readers or the writers. HANDLEhDataLock; // The count of the number of readers. // Can legally be zero or one while // a writer has the data locked.intnReaderCount;} RWLock;//// Reader/Writer prototypes//BOOL InitRWLock(RWLock *pLock);BOOL DestroyRWLock(RWLock *pLock);BOOL AcquireReadLock(RWLock *pLock);int ReleaseReadLock(RWLock *pLock);BOOL AcquireWriteLock(RWLock *pLock);int ReleaseWriteLock(RWLock *pLock);BOOL ReadOK(RWLock *pLock);BOOL WriteOK(RWLock *pLock);BOOL FatalError(char *s);
读者与写者算法:
#define WIN32_LEAN_AND_MEAN#include <stdio.h>#include <stdlib.h>#include <windows.h>#include "ReadWrit.h"// If we wait more than 2 seconds, then something is probably wrong!#define MAXIMUM_TIMEOUT 2000// Here's the pseudocode for what is going on://// Lock for Reader:// Lock the mutex// Bump the count of readers// If this is the first reader, lock the data// Release the mutex//// Unlock for Reader:// Lock the mutex// Decrement the count of readers// If this is the last reader, unlock the data// Release the mutex//// Lock for Writer:// Lock the data//// Unlock for Reader:// Unlock the data///////////////////////////////////////////////////////BOOL MyWaitForSingleObject(HANDLE hObject){ DWORD result; result = WaitForSingleObject(hObject, MAXIMUM_TIMEOUT); // Comment this out if you want this to be non-fatal if (result != WAIT_OBJECT_0) FatalError("MyWaitForSingleObject - Wait failed, you probably forgot to call release!"); return (result == WAIT_OBJECT_0);}BOOL InitRWLock(RWLock *pLock){ pLock->nReaderCount = 0; pLock->hDataLock = CreateSemaphore(NULL, 1, 1, NULL); if (pLock->hDataLock == NULL) return FALSE; pLock->hMutex = CreateMutex(NULL, FALSE, NULL); if (pLock->hMutex == NULL) { CloseHandle(pLock->hDataLock); return FALSE; } return TRUE;}BOOL DestroyRWLock(RWLock *pLock){ DWORD result = WaitForSingleObject(pLock->hDataLock, 0); if (result == WAIT_TIMEOUT) return FatalError("DestroyRWLock - Can't destroy object, it's locked!"); CloseHandle(pLock->hMutex); CloseHandle(pLock->hDataLock); return TRUE;}BOOL AcquireReadLock(RWLock *pLock){ BOOL result = TRUE; if (!MyWaitForSingleObject(pLock->hMutex)) return FALSE; if(++pLock->nReaderCount == 1) result = MyWaitForSingleObject(pLock->hDataLock); ReleaseMutex(pLock->hMutex); return result;}BOOL ReleaseReadLock(RWLock *pLock){ int result; LONG lPrevCount; if (!MyWaitForSingleObject(pLock->hMutex)) return FALSE; if (--pLock->nReaderCount == 0) result = ReleaseSemaphore(pLock->hDataLock, 1, &lPrevCount); ReleaseMutex(pLock->hMutex); return result;}BOOL AcquireWriteLock(RWLock *pLock){ return MyWaitForSingleObject(pLock->hDataLock);}BOOL ReleaseWriteLock(RWLock *pLock){ int result; LONG lPrevCount; result = ReleaseSemaphore(pLock->hDataLock, 1, &lPrevCount); if (lPrevCount != 0) FatalError("ReleaseWriteLock - Semaphore was not locked!"); return result;}BOOL ReadOK(RWLock *pLock){ // This check is not perfect, because we // do not know for sure if we are one of // the readers. return (pLock->nReaderCount > 0);}BOOL WriteOK(RWLock *pLock){ DWORD result; // The first reader may be waiting in the mutex, // but any more than that is an error. if (pLock->nReaderCount > 1) return FALSE; // This check is not perfect, because we // do not know for sure if this thread was // the one that had the semaphore locked. result = WaitForSingleObject(pLock->hDataLock, 0); if (result == WAIT_TIMEOUT) return TRUE; // a count is kept, which was incremented in Wait. result = ReleaseSemaphore(pLock->hDataLock, 1, NULL); if (result == FALSE) FatalError("WriteOK - ReleaseSemaphore failed"); return FALSE;}////////////////////////////////////////////////////////* * Error handler */BOOL FatalError(char *s){ fprintf(stdout, "%s\n", s); // Comment out exit() to prevent termination exit(EXIT_FAILURE); return FALSE;}
主文件,多读者和写者对链表的操作
#define WIN32_LEAN_AND_MEAN#include <stdio.h>#include <stdlib.h>#include <windows.h>#include "ReadWrit.h"/////////////////////////////////////////////////////////// Structure definition//typedef struct _Node{ struct _Node *pNext; charszBuffer[80];} Node;typedef struct _List{RWLocklock; Node*pHead;} List;//// Linked list prototypes//BOOL InitRWLock(RWLock *pLock);BOOL DeleteList(List *pList);BOOL AddHead(List *pList, Node *node);BOOL DeleteHead(List *pList);BOOL Insert(List *pList, Node *afterNode, Node *newNode);Node *Next(List *pList, Node *node);//// Test functions prototypes//DWORD WINAPI LoadThreadFunc(LPVOID n);DWORD WINAPI SearchThreadFunc(LPVOID n);DWORD WINAPI DeleteThreadFunc(LPVOID n);//// Global variables//// This is the list we use for testingList *gpList;///////////////////////////////////////////////////////List *CreateList(){ List *pList = GlobalAlloc(GPTR, sizeof(List));if (InitRWLock(&pList->lock) == FALSE){GlobalFree(pList);pList = NULL;} return pList;}BOOL DeleteList(List *pList){AcquireWriteLock(&pList->lock);while (DeleteHead(pList));ReleaseWriteLock(&pList->lock);DestroyRWLock(&gpList->lock); GlobalFree(pList);return TRUE;}BOOL AddHead(List *pList, Node *pNode){if (!WriteOK(&pList->lock))return FatalError("AddHead - not allowed to write!"); pNode->pNext = pList->pHead; pList->pHead = pNode;}BOOL DeleteHead(List *pList){Node *pNode;if (!WriteOK(&pList->lock))return FatalError("AddHead - not allowed to write!");if (pList->pHead == NULL)return FALSE;pNode = pList->pHead->pNext;GlobalFree(pList->pHead); pList->pHead = pNode;return TRUE;}BOOL Insert(List *pList, Node *afterNode, Node *newNode){if (!WriteOK(&pList->lock))return FatalError("Insert - not allowed to write!"); if (afterNode == NULL) { AddHead(pList, newNode); } else { newNode->pNext = afterNode->pNext; afterNode->pNext = newNode; }}Node *Next(List *pList, Node *pNode){if (!ReadOK(&pList->lock)){FatalError("Next - Not allowed to read!");return NULL;}if (pNode == NULL)return pList->pHead;else return pNode->pNext;}///////////////////////////////////////////////////////DWORD WINAPI ThreadFunc(LPVOID);int main(){ HANDLE hThrds[4]; int slot = 0;intrc;intnThreadCount = 0; DWORDdwThreadId;gpList = CreateList();if (!gpList)FatalError("main - List creation failed!"); hThrds[nThreadCount++] = CreateThread(NULL, 0, LoadThreadFunc, 0, 0, &dwThreadId ); hThrds[nThreadCount++] = CreateThread(NULL, 0, SearchThreadFunc, (LPVOID)"pNode", 0, &dwThreadId ); hThrds[nThreadCount++] = CreateThread(NULL, 0, SearchThreadFunc, (LPVOID)"pList", 0, &dwThreadId ); hThrds[nThreadCount++] = CreateThread(NULL, 0, DeleteThreadFunc, 0, 0, &dwThreadId ); /* Now wait for all threads to terminate */ rc = WaitForMultipleObjects( nThreadCount, hThrds, TRUE, INFINITE ); for (slot=0; slot<nThreadCount; slot++) CloseHandle(hThrds[slot]); printf("\nProgram finished.\n");DeleteList(gpList); return EXIT_SUCCESS;}/* * Slowly load the contents of "List.c" into the * linked list. */DWORD WINAPI LoadThreadFunc(LPVOID n){int nBatchCount;Node *pNode;FILE* fp = fopen("List.c", "r");if (!fp){fprintf(stderr, "ReadWrit.c not found\n");exit(EXIT_FAILURE);}pNode = GlobalAlloc(GPTR, sizeof(Node));nBatchCount = (rand() % 10) + 2;AcquireWriteLock(&gpList->lock);while (fgets(pNode->szBuffer, sizeof(Node), fp)){AddHead(gpList, pNode);// Try not to hog the lockif (--nBatchCount == 0){ReleaseWriteLock(&gpList->lock);Sleep(rand() % 5);nBatchCount = (rand() % 10) + 2;AcquireWriteLock(&gpList->lock);}pNode = GlobalAlloc(GPTR, sizeof(Node));}ReleaseWriteLock(&gpList->lock);return 0;}/* * Every so often, walked the linked list * and figure out how many lines one string * appears (given as the startup param) */DWORD WINAPI SearchThreadFunc(LPVOID n){int i;char *szSearch = (char *)n;for (i=0; i<20; i++){intnFoundCount = 0;Node *next = NULL;AcquireReadLock(&gpList->lock);next = Next(gpList, next);while (next){if (strstr(next->szBuffer, szSearch))nFoundCount++;next = Next(gpList, next);}ReleaseReadLock(&gpList->lock);printf("Found %d lines with '%s'\n", nFoundCount, szSearch);Sleep((rand() % 30));} return 0;}/* * Every so often, delete some entries in the list. */DWORD WINAPI DeleteThreadFunc(LPVOID n){int i;for (i=0; i<100; i++){Sleep(1);AcquireWriteLock(&gpList->lock);DeleteHead(gpList);DeleteHead(gpList);DeleteHead(gpList);ReleaseWriteLock(&gpList->lock);} return 0;}
- 【win32多线程】数据的一致性问题,即多个线程读写数据问题
- 一致性控制——解决线程间数据传递问题
- 多线程2:线程操作共享数据所引发的问题
- SAP主数据与业务数据的一致性问题
- qt中读写二进制数据的问题
- 关于读写注册表二进制数据的问题
- 【Memcached】数据缓存一致性问题详解
- 巧用CAS解决数据并发一致性问题
- 多线程数据竞争问题
- 多线程内数据长效保护的问题
- EnterCriticalSection 多线程操作相同数据遇到的问题(线程锁)
- win32程序浮点数据精度问题
- APP 缓存数据线程安全问题,多个线程同时对同一资源进行读写问题
- Win32多线程问题
- 多线程下数据同步问题
- 多线程读脏数据问题
- win32多线程与动态分配内存的问题
- win32 多线程的问题(未解决)
- PHP手册-执行shell脚本
- 使用QT在windows下高精度测试程序运行时间
- 在Ubuntu上下载、编译和安装Android最新源代码
- hibernate条件查询-----模糊查询==占位符查询
- poj 2362 Square
- 【win32多线程】数据的一致性问题,即多个线程读写数据问题
- 编码实现字符串到整形数的转变
- cocos2d学习教程1:cocos2d基本概念
- ccsu 1090 积最大的整数分解
- Sitescope-Mysql & Loadrunner使用sitescope篇
- 上篇博文的终端命令记录,以供查阅
- @Override的作用
- 浅谈回声消除技术
- Qt到Cortex-A8的移植