单个写入程序/多个阅读程序的保护(转自Windows核心编程)

    许多应用程序存在一个基本的同步问题,这个问题称为单个写入程序/多个阅读程序环境。
该问题涉及到试图访问共享资源的任意数量的线程。这些线程中,有些线程(写入程序)需要
修改数据的内容,而有些线程(阅读程序)则需要读取数据。由于下面4个原则,它们之间的
同步是必要的:
1) 当一个线程正在写入数据时,其他任何线程不能写入数据。
2) 当一个线程正在写入数据时,其他任何线程不能读取数据。
3) 当一个线程正在读取数据时,其他任何线程不能写入数据。
4) 当一个线程正在读取数据时,其他线程也能够读取数据。

 

代码如下:

--------------------------------------------

SWMRG.h


#pragma once

#include <Windows.h>

class CSWMRG
{
public:
 CSWMRG(void);


public:
 ~CSWMRG(void);

 void WaitToRead();        // Call this to gain shared read access
 void WaitToWrite();       // Call this to gain exclusive write access
 void Done();                  // Call this when done accessing the resource

 

public:
 CRITICAL_SECTION m_cs;
 int m_nActive;
 int m_nWaitingReaders;
 int m_nWaitingWriters;
 HANDLE m_hsemReaders;
 HANDLE m_hsemWriters;

};

----------------------------------------------

SWMRG.cpp

 

#include "SWMRG.h"

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

 

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

 

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

 

 // Are there writers waiting ?
 bool bWaitingWrite = (m_nWaitingWriters || m_nActive < 0);

 

 // wait to read
 if(bWaitingWrite)
 {
  m_nWaitingReaders++;
 }
 else
 {
  // read the resource
  m_nActive++;
 }

 

 LeaveCriticalSection(&m_cs);

 if(bWaitingWrite)
  WaitForSingleObject(m_hsemReaders, INFINITE);
}

 

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

 

 // Are there readers waiting ?
 bool bWaitingRead = (m_nActive != 0);

 

 if (bWaitingRead)
 {
  m_nWaitingWriters++;
 }
 else
 {
  m_nActive = -1;
 }

 

 LeaveCriticalSection(&m_cs);

 if(bWaitingRead)
  WaitForSingleObject(m_hsemWriters, INFINITE);

}

 

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

 if(m_nActive)
 {
  m_nActive--;
 }
 else
 {
  m_nActive++;
 }

 

 HANDLE hsem = NULL;
 LONG lCount = 1;     // Assume only 1 waiter wakes; always true for writers

 if (m_nActive == 0)
 {
  if (m_nWaitingWriters > 0)
  {
   m_nActive = -1;
   m_nWaitingWriters--;
   hsem = m_hsemWriters;
  }
  else if (m_nWaitingReaders > 0)
  {
   m_nActive = m_nWaitingReaders;
   m_nWaitingReaders = 0;
   hsem = m_hsemReaders;
   lCount = m_nActive;
  }
 }

 

 LeaveCriticalSection(&m_cs);
 if (hsem != NULL)
 {
  ReleaseSemaphore(hsem, lCount, NULL);
 }

}

 

--------------------------------------------

Test.cpp

 

#include "SWMRG.h"
#include <tchar.h>
#include <process.h>       // for _beginthreadex
#include <BaseTsd.h>

CSWMRG g_swmrg;

unsigned __stdcall Thread(PVOID pvParam)
{
 TCHAR sz[50];
 //#define PtrToShort( p )  ((short)(LONG_PTR)(p) )
 wsprintf(sz, TEXT("SWMRG Test: Thread %d"), PtrToShort(pvParam));
 int n = MessageBox(NULL, TEXT("YES: Attempt to read/nNO: Attempt to write"), sz, MB_YESNO);

 // Attempt to read or write
 if (n == IDYES)
  g_swmrg.WaitToRead();
 else
  g_swmrg.WaitToWrite();

 MessageBox(NULL, (n == IDYES) ? TEXT("OK stops READING") : TEXT("OK stops WRITING"), sz, MB_OK);

 // Stop reading/writing
 g_swmrg.Done();
 return 0;
}

int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int)
{
 HANDLE hThread[5];
 int nThread = 0;
 for (nThread = 0; nThread < 5; nThread++)
 {
  DWORD dwThreadId = 0;
  hThread[nThread] = (HANDLE)_beginthreadex(NULL, 0, Thread, (void *)&nThread,  0, (unsigned *)&dwThreadId);
 }

 // Wait for all the threads to exit
 WaitForMultipleObjects(nThread, hThread, true, INFINITE);
 while (nThread--)
  CloseHandle(hThread[nThread]);

 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值