抄WINDOW核心编程中的 多单写多读锁,

来源:互联网 发布:复杂的sql语句 编辑:程序博客网 时间:2024/05/19 17:56

#pragma once
#include <windows.h>

class CSWMRG
{
public:
 CSWMRG(void);
 ~CSWMRG(void);

public:
 void WaitToRead();
 void WaitToWrite();
 void Done();

private:
 CRITICAL_SECTION m_cs;
 HANDLE           m_hsemReaders;
 HANDLE    m_hsemWriters;
 int     m_nWaitingReaders;
 int     m_nWaitingWriters; 
 int     m_nActives;
};

#include "StdAfx.h"
#include "./swmrg.h"

CSWMRG::CSWMRG(void)
{
 InitializeCriticalSection(&m_cs);
 m_hsemReaders = CreateSemaphore(NULL, 0, 65535, NULL);
 m_hsemWriters = CreateSemaphore(NULL, 0, 65535, NULL);
 m_nWaitingReaders = 0;
 m_nWaitingWriters = 0; 
 m_nActives = 0;
}

CSWMRG::~CSWMRG(void)
{
 CloseHandle(m_hsemWriters);
 CloseHandle(m_hsemReaders);
 DeleteCriticalSection(&m_cs);
 m_nWaitingReaders = 0;
 m_nWaitingWriters = 0; 
 m_nActives = 0;
}

void CSWMRG::WaitToRead()
{
 EnterCriticalSection(&m_cs);

 //只需要判断写, 因为可以同时读
 BOOL bWriting = ((m_nActives < 0) || (m_nWaitingWriters > 0));

 if (bWriting)
 {
  m_nWaitingReaders++;
 }
 else
 {
  m_nActives++;
 }
 
 LeaveCriticalSection(&m_cs);

 if (bWriting)
 {
  WaitForSingleObject(m_hsemReaders, -1);
 }
}

void CSWMRG::WaitToWrite()
{
 EnterCriticalSection(&m_cs);

 //只要有人正在读或写就不能写
 BOOL bBusy = (m_nActives != 0);
 if (bBusy)
 {
  m_nWaitingWriters++;
 }
 else
 {
  m_nActives = -1;
 }

 LeaveCriticalSection(&m_cs);

 if (bBusy)
 {
  WaitForSingleObject(&m_hsemWriters, -1);
 }
}

void CSWMRG::Done()
{
 EnterCriticalSection(&m_cs);
 if (m_nActives > 0)
 {
  m_nActives--;
 }
 else
 {
  m_nActives++;
 }

 HANDLE hSem = NULL;
 int    nCount = 1;

 if (m_nActives == 0)
 {
  if (m_nWaitingWriters > 0)
  {
   m_nActives = -1;
   m_nWaitingWriters--;
   hSem = m_hsemWriters;
  }
  else if (m_nWaitingReaders > 0)
  {
   //全部可读
   m_nActives = m_nWaitingReaders;
   m_nWaitingReaders = 0;
   hSem = m_hsemReaders;
   nCount = m_nWaitingReaders;
  }
 }

 LeaveCriticalSection(&m_cs);

 if (hSem)
 {
  ReleaseSemaphore(hSem, nCount, NULL);
 }
}

 

// CSWMRG.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "SWMRG.h"
#include <process.h>

unsigned int __stdcall  TestRead(void *pParam);
unsigned int __stdcall TestWrite(void *pParam);

CSWMRG g_swmrg;

int _tmain(int argc, _TCHAR* argv[])
{
 HANDLE hThread[5];
 wchar_t *pContent = new wchar_t[512];
 memset(pContent, '/0', 512);
 
 for (int i = 0; i < 3; i++)
 {
  hThread[i] = (HANDLE) _beginthreadex(NULL, 0,TestRead, pContent, 0, NULL);
 }
 for (int i = 3; i < 5; i++)
 {
  hThread[i] = (HANDLE) _beginthreadex(NULL, 0,TestWrite, pContent, 0, NULL);
 }

 WaitForMultipleObjects(5, hThread, TRUE, -1);

 delete[] pContent;
 for (int i = 0; i < 5; i++)
 {
  CloseHandle(hThread[i]);
 }
 
 wprintf(L"Game Over /r/n");

 getchar();

 return 0;
}

unsigned int __stdcall TestRead(void *pParam)
{
 wchar_t *pContent = (wchar_t *) pParam;
 if (NULL == pContent)
  return -1;

 for (int i = 0; i < 5; i++)
 {
  g_swmrg.WaitToRead();
  wprintf(pContent);
  Sleep(1000);
  g_swmrg.Done();
  Sleep(0);
 }

 return 1;
}

static int nThreadCount = 0;

unsigned int __stdcall TestWrite(void *pParam)
{
 wchar_t *pContent = (wchar_t *) pParam;
 if (NULL == pContent)
  return -1;

 int nThreadNum = nThreadCount;
 nThreadCount++;

 for (int i = 0; i < 3; i++)
 {
  g_swmrg.WaitToRead();
  wsprintfW(pContent, L"hread  = %d, Loop = %d/r/n", nThreadNum, i);
  Sleep(1000);
  g_swmrg.Done();
  
  Sleep(0);
 }
 return 1;
}