C++实现多线程读写锁

在Win32下用C++实现多线程读写锁


    读写锁实际是一种特殊的自旋锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。这种锁相对于自旋锁而言,能提高并发性,因为在多处理器系统中,它允许同时有多个读者来访问共享资源,最大可能的读者数为实际的逻辑CPU数。写者是排他性的,一个读写锁同时只能有一个写者或多个读者(与CPU数相关),但不能同时既有读者又有写者。

    现在Win32的API,用C++实现自己的读写锁。这组API包括:CreateMutex,CreateEvent,WaitForSingleObject,WaitForMultipleObjects,ResetEvent,ReleaseMutex,SetEvent,CloseHandle。以下代码在VS2005下,已经编译通过。

RWLockImpl.h


[cpp] view plaincopyprint?
01.#ifndef _RWLockImpl_Header  
02.#define _RWLockImpl_Header  
03. 
04.#include <assert.h>  
05.#include <iostream>  
06.#include <Windows.h>  
07.#include <process.h>  
08. 
09.using namespace std; 
10. 
11./*
12. 读写锁允许当前的多个读用户访问保护资源,但只允许一个写读者访问保护资源
13.*/ 
14. 
15.//-----------------------------------------------------------------  
16.class CRWLockImpl 
17.{ 
18.protected: 
19.    CRWLockImpl(); 
20.    ~CRWLockImpl(); 
21.    void ReadLockImpl(); 
22.    bool TryReadLockImpl(); 
23.    void WriteLockImpl(); 
24.    bool TryWriteLockImpl(); 
25.    void UnlockImpl(); 
26. 
27.private: 
28.    void AddWriter(); 
29.    void RemoveWriter(); 
30.    DWORD TryReadLockOnce(); 
31. 
32.    HANDLE   m_mutex; 
33.    HANDLE   m_readEvent; 
34.    HANDLE   m_writeEvent; 
35.    unsigned m_readers; 
36.    unsigned m_writersWaiting; 
37.    unsigned m_writers; 
38.}; 
39. 
40.//-----------------------------------------------------------------  
41. 
42.class CMyRWLock: private CRWLockImpl 
43.{ 
44.public: 
45. 
46.    //创建读/写锁  
47.    CMyRWLock(){}; 
48. 
49.    //销毁读/写锁  
50.    ~CMyRWLock(){}; 
51. 
52.    //获取读锁  
53.    //如果其它一个线程占有写锁,则当前线程必须等待写锁被释放,才能对保护资源进行访问  
54.    void ReadLock(); 
55. 
56.    //尝试获取一个读锁  
57.    //如果获取成功,则立即返回true,否则当另一个线程占有写锁,则返回false  
58.    bool TryReadLock(); 
59. 
60.    //获取写锁  
61.    //如果一个或更多线程占有读锁,则必须等待所有锁被释放  
62.    //如果相同的一个线程已经占有一个读锁或写锁,则返回结果不确定  
63.    void WriteLock(); 
64. 
65.    //尝试获取一个写锁  
66.    //如果获取成功,则立即返回true,否则当一个或更多其它线程占有读锁,返回false  
67.    //如果相同的一个线程已经占有一个读锁或写锁,则返回结果不确定  
68.    bool TryWriteLock(); 
69. 
70.    //释放一个读锁或写锁  
71.    void Unlock(); 
72. 
73.private: 
74.    CMyRWLock(const CMyRWLock&); 
75.    CMyRWLock& operator = (const CMyRWLock&); 
76.}; 
77. 
78.inline void CMyRWLock::ReadLock() 
79.{ 
80.    ReadLockImpl(); 
81.} 
82. 
83.inline bool CMyRWLock::TryReadLock() 
84.{ 
85.    return TryReadLockImpl(); 
86.} 
87. 
88.inline void CMyRWLock::WriteLock() 
89.{ 
90.    WriteLockImpl(); 
91.} 
92. 
93.inline bool CMyRWLock::TryWriteLock() 
94.{ 
95.    return TryWriteLockImpl(); 
96.} 
97. 
98.inline void CMyRWLock::Unlock() 
99.{ 
100.    UnlockImpl(); 
101.} 
102. 
103. 
104.#endif 
#ifndef _RWLockImpl_Header
#define _RWLockImpl_Header

#include <assert.h>
#include <iostream>
#include <Windows.h>
#include <process.h>

using namespace std;

/*
 读写锁允许当前的多个读用户访问保护资源,但只允许一个写读者访问保护资源
*/

//-----------------------------------------------------------------
class CRWLockImpl
{
protected:
 CRWLockImpl();
 ~CRWLockImpl();
 void ReadLockImpl();
 bool TryReadLockImpl();
 void WriteLockImpl();
 bool TryWriteLockImpl();
 void UnlockImpl();

private:
 void AddWriter();
 void RemoveWriter();
 DWORD TryReadLockOnce();

 HANDLE   m_mutex;
 HANDLE   m_readEvent;
 HANDLE   m_writeEvent;
 unsigned m_readers;
 unsigned m_writersWaiting;
 unsigned m_writers;
};

//-----------------------------------------------------------------

class CMyRWLock: private CRWLockImpl
{
public:

 //创建读/写锁
 CMyRWLock(){};

 //销毁读/写锁
 ~CMyRWLock(){};

 //获取读锁
 //如果其它一个线程占有写锁,则当前线程必须等待写锁被释放,才能对保护资源进行访问
 void ReadLock();

 //尝试获取一个读锁
 //如果获取成功,则立即返回true,否则当另一个线程占有写锁,则返回false
 bool TryReadLock();

 //获取写锁
 //如果一个或更多线程占有读锁,则必须等待所有锁被释放
 //如果相同的一个线程已经占有一个读锁或写锁,则返回结果不确定
 void WriteLock();

 //尝试获取一个写锁
 //如果获取成功,则立即返回true,否则当一个或更多其它线程占有读锁,返回false
 //如果相同的一个线程已经占有一个读锁或写锁,则返回结果不确定
 bool TryWriteLock();

 //释放一个读锁或写锁
 void Unlock();

private:
 CMyRWLock(const CMyRWLock&);
 CMyRWLock& operator = (const CMyRWLock&);
};

inline void CMyRWLock::ReadLock()
{
 ReadLockImpl();
}

inline bool CMyRWLock::TryReadLock()
{
 return TryReadLockImpl();
}

inline void CMyRWLock::WriteLock()
{
 WriteLockImpl();
}

inline bool CMyRWLock::TryWriteLock()
{
 return TryWriteLockImpl();
}

inline void CMyRWLock::Unlock()
{
 UnlockImpl();
}


#endif RWLockImpl.cpp


[cpp] view plaincopyprint?
01.#include "RWLockImpl.h"  
02. 
03.CRWLockImpl::CRWLockImpl(): m_readers(0), m_writersWaiting(0), m_writers(0) 
04.{ 
05.    m_mutex = CreateMutex(NULL, FALSE, NULL); 
06.    if (m_mutex == NULL) 
07.        cout<<"cannot create reader/writer lock"<<endl; 
08. 
09.    m_readEvent = CreateEvent(NULL, TRUE, TRUE, NULL); 
10.    if (m_readEvent == NULL) 
11.        cout<<"cannot create reader/writer lock"<<endl; 
12. 
13.    m_writeEvent = CreateEvent(NULL, TRUE, TRUE, NULL); 
14.    if (m_writeEvent == NULL) 
15.        cout<<"cannot create reader/writer lock"<<endl; 
16.} 
17. 
18.CRWLockImpl::~CRWLockImpl() 
19.{ 
20.    CloseHandle(m_mutex); 
21.    CloseHandle(m_readEvent); 
22.    CloseHandle(m_writeEvent); 
23.} 
24. 
25.inline void CRWLockImpl::AddWriter() 
26.{ 
27.    switch (WaitForSingleObject(m_mutex, INFINITE)) 
28.    { 
29.    case WAIT_OBJECT_0: 
30.        if (++m_writersWaiting == 1)  
31.            ResetEvent(m_readEvent); 
32.        ReleaseMutex(m_mutex); 
33.        break; 
34.    default: 
35.        cout<<"cannot lock reader/writer lock"<<endl; 
36.    } 
37.} 
38. 
39.inline void CRWLockImpl::RemoveWriter() 
40.{ 
41.    switch (WaitForSingleObject(m_mutex, INFINITE)) 
42.    { 
43.    case WAIT_OBJECT_0: 
44.        if (--m_writersWaiting == 0 && m_writers == 0)  
45.            SetEvent(m_readEvent); 
46.        ReleaseMutex(m_mutex); 
47.        break; 
48.    default: 
49.        cout<<"cannot lock reader/writer lock"<<endl; 
50.    } 
51.} 
52. 
53.void CRWLockImpl::ReadLockImpl() 
54.{ 
55.    HANDLE h[2]; 
56.    h[0] = m_mutex; 
57.    h[1] = m_readEvent; 
58.    switch (WaitForMultipleObjects(2, h, TRUE, INFINITE)) 
59.    { 
60.    case WAIT_OBJECT_0: 
61.    case WAIT_OBJECT_0 + 1: 
62.        ++m_readers; 
63.        ResetEvent(m_writeEvent); 
64.        ReleaseMutex(m_mutex); 
65.        assert(m_writers == 0); 
66.        break; 
67.    default: 
68.        cout<<"cannot lock reader/writer lock"<<endl; 
69.    } 
70.} 
71. 
72.bool CRWLockImpl::TryReadLockImpl() 
73.{ 
74.    for (;;) 
75.    { 
76.        if (m_writers != 0 || m_writersWaiting != 0) 
77.            return false; 
78. 
79.        DWORD result = TryReadLockOnce(); 
80.        switch (result) 
81.        { 
82.        case WAIT_OBJECT_0: 
83.        case WAIT_OBJECT_0 + 1: 
84.            return true; 
85.        case WAIT_TIMEOUT: 
86.            continue; 
87.        default: 
88.            cout<<"cannot lock reader/writer lock"<<endl; 
89.        } 
90.    } 
91.} 
92. 
93.void CRWLockImpl::WriteLockImpl() 
94.{ 
95.    AddWriter(); 
96.    HANDLE h[2]; 
97.    h[0] = m_mutex; 
98.    h[1] = m_writeEvent; 
99.    switch (WaitForMultipleObjects(2, h, TRUE, INFINITE)) 
100.    { 
101.    case WAIT_OBJECT_0: 
102.    case WAIT_OBJECT_0 + 1: 
103.        --m_writersWaiting; 
104.        ++m_readers; 
105.        ++m_writers; 
106.        ResetEvent(m_readEvent); 
107.        ResetEvent(m_writeEvent); 
108.        ReleaseMutex(m_mutex); 
109.        assert(m_writers == 1); 
110.        break; 
111.    default: 
112.        RemoveWriter(); 
113.        cout<<"cannot lock reader/writer lock"<<endl; 
114.    } 
115.} 
116. 
117.bool CRWLockImpl::TryWriteLockImpl() 
118.{ 
119.    AddWriter(); 
120.    HANDLE h[2]; 
121.    h[0] = m_mutex; 
122.    h[1] = m_writeEvent; 
123.    switch (WaitForMultipleObjects(2, h, TRUE, 1)) 
124.    { 
125.    case WAIT_OBJECT_0: 
126.    case WAIT_OBJECT_0 + 1: 
127.        --m_writersWaiting; 
128.        ++m_readers; 
129.        ++m_writers; 
130.        ResetEvent(m_readEvent); 
131.        ResetEvent(m_writeEvent); 
132.        ReleaseMutex(m_mutex); 
133.        assert(m_writers == 1); 
134.        return true; 
135.    case WAIT_TIMEOUT: 
136.        RemoveWriter(); 
137.    default: 
138.        RemoveWriter(); 
139.        cout<<"cannot lock reader/writer lock"<<endl; 
140.    } 
141.    return false; 
142.} 
143. 
144.void CRWLockImpl::UnlockImpl() 
145.{ 
146.    switch (WaitForSingleObject(m_mutex, INFINITE)) 
147.    { 
148.    case WAIT_OBJECT_0: 
149.        m_writers = 0; 
150.        if (m_writersWaiting == 0) SetEvent(m_readEvent); 
151.        if (--m_readers == 0) SetEvent(m_writeEvent); 
152.        ReleaseMutex(m_mutex); 
153.        break; 
154.    default: 
155.        cout<<"cannot unlock reader/writer lock"<<endl; 
156.    } 
157.} 
158. 
159.DWORD CRWLockImpl::TryReadLockOnce() 
160.{ 
161.    HANDLE h[2]; 
162.    h[0] = m_mutex; 
163.    h[1] = m_readEvent; 
164.    DWORD result = WaitForMultipleObjects(2, h, TRUE, 1);  
165.    switch (result) 
166.    { 
167.    case WAIT_OBJECT_0: 
168.    case WAIT_OBJECT_0 + 1: 
169.        ++m_readers; 
170.        ResetEvent(m_writeEvent); 
171.        ReleaseMutex(m_mutex); 
172.        assert(m_writers == 0); 
173.        return result; 
174.    case WAIT_TIMEOUT: 
175.    default: 
176.        cout<<"cannot lock reader/writer lock"<<endl; 
177.    } 
178.    return result; 
179.} 
#include "RWLockImpl.h"

CRWLockImpl::CRWLockImpl(): m_readers(0), m_writersWaiting(0), m_writers(0)
{
 m_mutex = CreateMutex(NULL, FALSE, NULL);
 if (m_mutex == NULL)
  cout<<"cannot create reader/writer lock"<<endl;

 m_readEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
 if (m_readEvent == NULL)
  cout<<"cannot create reader/writer lock"<<endl;

 m_writeEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
 if (m_writeEvent == NULL)
  cout<<"cannot create reader/writer lock"<<endl;
}

CRWLockImpl::~CRWLockImpl()
{
 CloseHandle(m_mutex);
 CloseHandle(m_readEvent);
 CloseHandle(m_writeEvent);
}

inline void CRWLockImpl::AddWriter()
{
 switch (WaitForSingleObject(m_mutex, INFINITE))
 {
 case WAIT_OBJECT_0:
  if (++m_writersWaiting == 1)
   ResetEvent(m_readEvent);
  ReleaseMutex(m_mutex);
  break;
 default:
  cout<<"cannot lock reader/writer lock"<<endl;
 }
}

inline void CRWLockImpl::RemoveWriter()
{
 switch (WaitForSingleObject(m_mutex, INFINITE))
 {
 case WAIT_OBJECT_0:
  if (--m_writersWaiting == 0 && m_writers == 0)
   SetEvent(m_readEvent);
  ReleaseMutex(m_mutex);
  break;
 default:
  cout<<"cannot lock reader/writer lock"<<endl;
 }
}

void CRWLockImpl::ReadLockImpl()
{
 HANDLE h[2];
 h[0] = m_mutex;
 h[1] = m_readEvent;
 switch (WaitForMultipleObjects(2, h, TRUE, INFINITE))
 {
 case WAIT_OBJECT_0:
 case WAIT_OBJECT_0 + 1:
  ++m_readers;
  ResetEvent(m_writeEvent);
  ReleaseMutex(m_mutex);
  assert(m_writers == 0);
  break;
 default:
  cout<<"cannot lock reader/writer lock"<<endl;
 }
}

bool CRWLockImpl::TryReadLockImpl()
{
 for (;;)
 {
  if (m_writers != 0 || m_writersWaiting != 0)
   return false;

  DWORD result = TryReadLockOnce();
  switch (result)
  {
  case WAIT_OBJECT_0:
  case WAIT_OBJECT_0 + 1:
   return true;
  case WAIT_TIMEOUT:
   continue;
  default:
   cout<<"cannot lock reader/writer lock"<<endl;
  }
 }
}

void CRWLockImpl::WriteLockImpl()
{
 AddWriter();
 HANDLE h[2];
 h[0] = m_mutex;
 h[1] = m_writeEvent;
 switch (WaitForMultipleObjects(2, h, TRUE, INFINITE))
 {
 case WAIT_OBJECT_0:
 case WAIT_OBJECT_0 + 1:
  --m_writersWaiting;
  ++m_readers;
  ++m_writers;
  ResetEvent(m_readEvent);
  ResetEvent(m_writeEvent);
  ReleaseMutex(m_mutex);
  assert(m_writers == 1);
  break;
 default:
  RemoveWriter();
  cout<<"cannot lock reader/writer lock"<<endl;
 }
}

bool CRWLockImpl::TryWriteLockImpl()
{
 AddWriter();
 HANDLE h[2];
 h[0] = m_mutex;
 h[1] = m_writeEvent;
 switch (WaitForMultipleObjects(2, h, TRUE, 1))
 {
 case WAIT_OBJECT_0:
 case WAIT_OBJECT_0 + 1:
  --m_writersWaiting;
  ++m_readers;
  ++m_writers;
  ResetEvent(m_readEvent);
  ResetEvent(m_writeEvent);
  ReleaseMutex(m_mutex);
  assert(m_writers == 1);
  return true;
 case WAIT_TIMEOUT:
  RemoveWriter();
 default:
  RemoveWriter();
  cout<<"cannot lock reader/writer lock"<<endl;
 }
 return false;
}

void CRWLockImpl::UnlockImpl()
{
 switch (WaitForSingleObject(m_mutex, INFINITE))
 {
 case WAIT_OBJECT_0:
  m_writers = 0;
  if (m_writersWaiting == 0) SetEvent(m_readEvent);
  if (--m_readers == 0) SetEvent(m_writeEvent);
  ReleaseMutex(m_mutex);
  break;
 default:
  cout<<"cannot unlock reader/writer lock"<<endl;
 }
}

DWORD CRWLockImpl::TryReadLockOnce()
{
 HANDLE h[2];
 h[0] = m_mutex;
 h[1] = m_readEvent;
 DWORD result = WaitForMultipleObjects(2, h, TRUE, 1);
 switch (result)
 {
 case WAIT_OBJECT_0:
 case WAIT_OBJECT_0 + 1:
  ++m_readers;
  ResetEvent(m_writeEvent);
  ReleaseMutex(m_mutex);
  assert(m_writers == 0);
  return result;
 case WAIT_TIMEOUT:
 default:
  cout<<"cannot lock reader/writer lock"<<endl;
 }
 return result;
}
    下边是测试代码


[cpp] view plaincopyprint?
01.// MyRWLockWin32.cpp : 定义控制台应用程序的入口点。  
02.//  
03. 
04.#include "RWLockImpl.h"  
05. 
06.//创建一个读写锁对象  
07.CMyRWLock g_myRWLock; 
08.volatile int g_counter = 0; 
09. 
10.//线程函数  
11.unsigned int __stdcall StartThread(void *pParam) 
12.{ 
13.    int lastCount = 0; 
14.    for (int i = 0; i < 10000; ++i) 
15.    { 
16.        g_myRWLock.ReadLock(); 
17.        lastCount = g_counter; 
18.        //在读锁域,两个线程不断循环交替访问全局变量g_counter  
19.        for (int k = 0; k < 100; ++k) 
20.        { 
21.            if (g_counter != lastCount)  
22.                cout<<"the value of g_counter has been updated."<<endl; 
23.            Sleep(0); 
24.        } 
25.        g_myRWLock.Unlock(); 
26. 
27. 
28.        g_myRWLock.WriteLock(); 
29.        //在写锁域,只有一个线程可以修改全局变量g_counter的值  
30.        for (int k = 0; k < 100; ++k) 
31.        { 
32.            --g_counter; 
33.            Sleep(0); 
34.        } 
35.        for (int k = 0; k < 100; ++k) 
36.        { 
37.            ++g_counter; 
38.            Sleep(0); 
39.        } 
40.        ++g_counter; 
41.        if (g_counter <= lastCount)  
42.            cout<<"the value of g_counter is error."<<endl; 
43.        g_myRWLock.Unlock(); 
44.    } 
45.     
46.    return (unsigned int)0; 
47.} 
48. 
49.int main(int argc, char* argv[]) 
50.{ 
51.    HANDLE hThread1, hThread2; 
52.    unsigned int uiThreadId1, uiThreadId2; 
53. 
54.    //创建两个工作线程  
55.    hThread1 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)NULL, 0, &uiThreadId1); 
56.    hThread2 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)NULL, 0, &uiThreadId2); 
57. 
58.    //等待线程结束  
59.    DWORD dwRet = WaitForSingleObject(hThread1,INFINITE); 
60.    if ( dwRet == WAIT_TIMEOUT ) 
61.    { 
62.        TerminateThread(hThread1,0); 
63.    } 
64.    dwRet = WaitForSingleObject(hThread2,INFINITE); 
65.    if ( dwRet == WAIT_TIMEOUT ) 
66.    { 
67.        TerminateThread(hThread2,0); 
68.    } 
69. 
70.    //关闭线程句柄,释放资源  
71.    CloseHandle(hThread1); 
72.    CloseHandle(hThread2); 
73. 
74.    assert (g_counter == 20000); 
75. 
76.    system("pause"); 
77.    return 0; 
78.} 
// MyRWLockWin32.cpp : 定义控制台应用程序的入口点。
//

#include "RWLockImpl.h"

//创建一个读写锁对象
CMyRWLock g_myRWLock;
volatile int g_counter = 0;

//线程函数
unsigned int __stdcall StartThread(void *pParam)
{
 int lastCount = 0;
 for (int i = 0; i < 10000; ++i)
 {
  g_myRWLock.ReadLock();
  lastCount = g_counter;
  //在读锁域,两个线程不断循环交替访问全局变量g_counter
  for (int k = 0; k < 100; ++k)
  {
   if (g_counter != lastCount)
    cout<<"the value of g_counter has been updated."<<endl;
   Sleep(0);
  }
  g_myRWLock.Unlock();


  g_myRWLock.WriteLock();
  //在写锁域,只有一个线程可以修改全局变量g_counter的值
  for (int k = 0; k < 100; ++k)
  {
   --g_counter;
   Sleep(0);
  }
  for (int k = 0; k < 100; ++k)
  {
   ++g_counter;
   Sleep(0);
  }
  ++g_counter;
  if (g_counter <= lastCount)
   cout<<"the value of g_counter is error."<<endl;
  g_myRWLock.Unlock();
 }
 
 return (unsigned int)0;
}

int main(int argc, char* argv[])
{
 HANDLE hThread1, hThread2;
 unsigned int uiThreadId1, uiThreadId2;

 //创建两个工作线程
 hThread1 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)NULL, 0, &uiThreadId1);
 hThread2 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)NULL, 0, &uiThreadId2);

 //等待线程结束
 DWORD dwRet = WaitForSingleObject(hThread1,INFINITE);
 if ( dwRet == WAIT_TIMEOUT )
 {
  TerminateThread(hThread1,0);
 }
 dwRet = WaitForSingleObject(hThread2,INFINITE);
 if ( dwRet == WAIT_TIMEOUT )
 {
  TerminateThread(hThread2,0);
 }

 //关闭线程句柄,释放资源
 CloseHandle(hThread1);
 CloseHandle(hThread2);

 assert (g_counter == 20000);

 system("pause");
 return 0;
}
欢迎转载,麻烦带上链接:http://blog.csdn.net/chexlong/article/details/7110060 谢谢合作!

 

Linux平台用C++封装线程读写锁

    在Linux平台上已经有现成的线程读写锁pthread_rwlock_t以及相关API,现将这些API封装成与Win32平台上相同的接口,以便于编写跨平台程序。这些API包括pthread_rwlock_init,pthread_rwlock_rdlock,pthread_rwlock_tryrdlock,pthread_rwlock_wrlock,pthread_rwlock_trywrlock,pthread_rwlock_unlock,pthread_rwlock_destroy,可在Linux在线手册上查阅它们的说明。下边的代码在VS2005中编辑,在Fedora 13虚拟机中编译,测试通过。

RWLockImpl.h

 

[cpp] view plaincopyprint?
01.#ifndef _RWLockImpl_Header  
02.#define _RWLockImpl_Header  
03. 
04.#include <iostream>  
05.#include <pthread.h>  
06.#include <errno.h>  
07.#include <assert.h>  
08. 
09.using namespace std; 
10. 
11./*
12. 读写锁允许当前的多个读用户访问保护资源,但只允许一个写读者访问保护资源
13.*/ 
14. 
15.//-----------------------------------------------------------------  
16.class CRWLockImpl 
17.{ 
18.protected: 
19.    CRWLockImpl(); 
20.    ~CRWLockImpl(); 
21.    void ReadLockImpl(); 
22.    bool TryReadLockImpl(); 
23.    void WriteLockImpl(); 
24.    bool TryWriteLockImpl(); 
25.    void UnlockImpl(); 
26. 
27.private: 
28.    pthread_rwlock_t m_rwl; 
29.}; 
30. 
31.//-----------------------------------------------------------------  
32. 
33.class CMyRWLock: private CRWLockImpl 
34.{ 
35.public: 
36. 
37.    //创建读/写锁  
38.    CMyRWLock(){}; 
39. 
40.    //销毁读/写锁  
41.    ~CMyRWLock(){}; 
42. 
43.    //获取读锁  
44.    //如果其它一个线程占有写锁,则当前线程必须等待写锁被释放,才能对保护资源进行访问  
45.    void ReadLock(); 
46. 
47.    //尝试获取一个读锁  
48.    //如果获取成功,则立即返回true,否则当另一个线程占有写锁,则返回false  
49.    bool TryReadLock(); 
50. 
51.    //获取写锁  
52.    //如果一个或更多线程占有读锁,则必须等待所有锁被释放  
53.    //如果相同的一个线程已经占有一个读锁或写锁,则返回结果不确定  
54.    void WriteLock(); 
55. 
56.    //尝试获取一个写锁  
57.    //如果获取成功,则立即返回true,否则当一个或更多其它线程占有读锁,返回false  
58.    //如果相同的一个线程已经占有一个读锁或写锁,则返回结果不确定  
59.    bool TryWriteLock(); 
60. 
61.    //释放一个读锁或写锁  
62.    void Unlock(); 
63. 
64.private: 
65.    CMyRWLock(const CMyRWLock&); 
66.    CMyRWLock& operator = (const CMyRWLock&); 
67.}; 
68. 
69.inline void CMyRWLock::ReadLock() 
70.{ 
71.    ReadLockImpl(); 
72.} 
73. 
74.inline bool CMyRWLock::TryReadLock() 
75.{ 
76.    return TryReadLockImpl(); 
77.} 
78. 
79.inline void CMyRWLock::WriteLock() 
80.{ 
81.    WriteLockImpl(); 
82.} 
83. 
84.inline bool CMyRWLock::TryWriteLock() 
85.{ 
86.    return TryWriteLockImpl(); 
87.} 
88. 
89.inline void CMyRWLock::Unlock() 
90.{ 
91.    UnlockImpl(); 
92.} 
93. 
94.#endif 
#ifndef _RWLockImpl_Header
#define _RWLockImpl_Header

#include <iostream>
#include <pthread.h>
#include <errno.h>
#include <assert.h>

using namespace std;

/*
 读写锁允许当前的多个读用户访问保护资源,但只允许一个写读者访问保护资源
*/

//-----------------------------------------------------------------
class CRWLockImpl
{
protected:
 CRWLockImpl();
 ~CRWLockImpl();
 void ReadLockImpl();
 bool TryReadLockImpl();
 void WriteLockImpl();
 bool TryWriteLockImpl();
 void UnlockImpl();

private:
 pthread_rwlock_t m_rwl;
};

//-----------------------------------------------------------------

class CMyRWLock: private CRWLockImpl
{
public:

 //创建读/写锁
 CMyRWLock(){};

 //销毁读/写锁
 ~CMyRWLock(){};

 //获取读锁
 //如果其它一个线程占有写锁,则当前线程必须等待写锁被释放,才能对保护资源进行访问
 void ReadLock();

 //尝试获取一个读锁
 //如果获取成功,则立即返回true,否则当另一个线程占有写锁,则返回false
 bool TryReadLock();

 //获取写锁
 //如果一个或更多线程占有读锁,则必须等待所有锁被释放
 //如果相同的一个线程已经占有一个读锁或写锁,则返回结果不确定
 void WriteLock();

 //尝试获取一个写锁
 //如果获取成功,则立即返回true,否则当一个或更多其它线程占有读锁,返回false
 //如果相同的一个线程已经占有一个读锁或写锁,则返回结果不确定
 bool TryWriteLock();

 //释放一个读锁或写锁
 void Unlock();

private:
 CMyRWLock(const CMyRWLock&);
 CMyRWLock& operator = (const CMyRWLock&);
};

inline void CMyRWLock::ReadLock()
{
 ReadLockImpl();
}

inline bool CMyRWLock::TryReadLock()
{
 return TryReadLockImpl();
}

inline void CMyRWLock::WriteLock()
{
 WriteLockImpl();
}

inline bool CMyRWLock::TryWriteLock()
{
 return TryWriteLockImpl();
}

inline void CMyRWLock::Unlock()
{
 UnlockImpl();
}

#endifRWLockImpl.cpp


[cpp] view plaincopyprint?
01.#include "RWLockImpl.h"  
02. 
03.CRWLockImpl::CRWLockImpl() 
04.{ 
05.    if (pthread_rwlock_init(&m_rwl, NULL)) 
06.        cout<<"cannot create reader/writer lock"<<endl; 
07.} 
08. 
09.CRWLockImpl::~CRWLockImpl() 
10.{ 
11.    pthread_rwlock_destroy(&m_rwl); 
12.} 
13. 
14.void CRWLockImpl::ReadLockImpl() 
15.{ 
16.    if (pthread_rwlock_rdlock(&m_rwl))  
17.        cout<<"cannot lock reader/writer lock"<<endl; 
18.} 
19. 
20.bool CRWLockImpl::TryReadLockImpl() 
21.{ 
22.    int rc = pthread_rwlock_tryrdlock(&m_rwl); 
23.    if (rc == 0) 
24.        return true; 
25.    else if (rc == EBUSY) 
26.        return false; 
27.    else 
28.        cout<<"cannot lock reader/writer lock"<<endl; 
29. 
30.    return false; 
31.} 
32. 
33.void CRWLockImpl::WriteLockImpl() 
34.{ 
35.    if (pthread_rwlock_wrlock(&m_rwl))  
36.        cout<<"cannot lock reader/writer lock"<<endl; 
37.} 
38. 
39.bool CRWLockImpl::TryWriteLockImpl() 
40.{ 
41.    int rc = pthread_rwlock_trywrlock(&m_rwl); 
42.    if (rc == 0) 
43.        return true; 
44.    else if (rc == EBUSY) 
45.        return false; 
46.    else 
47.        cout<<"cannot lock reader/writer lock"<<endl; 
48.    return false; 
49.} 
50. 
51.void CRWLockImpl::UnlockImpl() 
52.{ 
53.    if (pthread_rwlock_unlock(&m_rwl)) 
54.        cout<<"cannot unlock reader/writer lock"<<endl; 
55.} 
#include "RWLockImpl.h"

CRWLockImpl::CRWLockImpl()
{
 if (pthread_rwlock_init(&m_rwl, NULL))
  cout<<"cannot create reader/writer lock"<<endl;
}

CRWLockImpl::~CRWLockImpl()
{
 pthread_rwlock_destroy(&m_rwl);
}

void CRWLockImpl::ReadLockImpl()
{
 if (pthread_rwlock_rdlock(&m_rwl))
  cout<<"cannot lock reader/writer lock"<<endl;
}

bool CRWLockImpl::TryReadLockImpl()
{
 int rc = pthread_rwlock_tryrdlock(&m_rwl);
 if (rc == 0)
  return true;
 else if (rc == EBUSY)
  return false;
 else
  cout<<"cannot lock reader/writer lock"<<endl;

 return false;
}

void CRWLockImpl::WriteLockImpl()
{
 if (pthread_rwlock_wrlock(&m_rwl))
  cout<<"cannot lock reader/writer lock"<<endl;
}

bool CRWLockImpl::TryWriteLockImpl()
{
 int rc = pthread_rwlock_trywrlock(&m_rwl);
 if (rc == 0)
  return true;
 else if (rc == EBUSY)
  return false;
 else
  cout<<"cannot lock reader/writer lock"<<endl;
 return false;
}

void CRWLockImpl::UnlockImpl()
{
 if (pthread_rwlock_unlock(&m_rwl))
  cout<<"cannot unlock reader/writer lock"<<endl;
}

    下边是测试代码


[cpp] view plaincopyprint?
01.// pthread_rwlock.cpp : 定义控制台应用程序的入口点。  
02.//  
03. 
04.#include "RWLockImpl.h"  
05. 
06.//创建一个读写锁对象  
07.CMyRWLock g_myRWLock; 
08.volatile int g_counter = 0; 
09. 
10.//线程函数  
11.void * StartThread(void *pParam) 
12.{ 
13.    int lastCount = 0; 
14.    for (int i = 0; i < 10000; ++i) 
15.    { 
16.        g_myRWLock.ReadLock(); 
17.        lastCount = g_counter; 
18.        //在读锁域,两个线程不断循环交替访问全局变量g_counter  
19.        for (int k = 0; k < 100; ++k) 
20.        { 
21.            if (g_counter != lastCount)  
22.                cout<<"the value of g_counter has been updated."<<endl; 
23.            sleep(0); 
24.        } 
25.        g_myRWLock.Unlock(); 
26. 
27. 
28.        g_myRWLock.WriteLock(); 
29.        //在写锁域,只有一个线程可以修改全局变量g_counter的值  
30.        for (int k = 0; k < 100; ++k) 
31.        { 
32.            --g_counter; 
33.            sleep(0); 
34.        } 
35.        for (int k = 0; k < 100; ++k) 
36.        { 
37.            ++g_counter; 
38.            sleep(0); 
39.        } 
40.        ++g_counter; 
41.        if (g_counter <= lastCount)  
42.            cout<<"the value of g_counter is error."<<endl; 
43.        g_myRWLock.Unlock(); 
44.    } 
45. 
46.    return (void *)0; 
47.} 
48. 
49.int main(int argc, char* argv[]) 
50.{ 
51.    pthread_t thread1,thread2; 
52.    pthread_attr_t attr1,attr2; 
53. 
54.    //创建两个工作线程  
55.    pthread_attr_init(&attr1); 
56.    pthread_attr_setdetachstate(&attr1,PTHREAD_CREATE_JOINABLE); 
57.    if (pthread_create(&thread1,&attr1, StartThread,0) == -1) 
58.    { 
59.        cout<<"Thread 1: create failed"<<endl; 
60.    } 
61.    pthread_attr_init(&attr2); 
62.    pthread_attr_setdetachstate(&attr2,PTHREAD_CREATE_JOINABLE); 
63.    if (pthread_create(&thread2,&attr2, StartThread,0) == -1) 
64.    { 
65.        cout<<"Thread 2: create failed"<<endl; 
66.    } 
67. 
68.    //等待线程结束  
69.    void *result; 
70.    pthread_join(thread1,&result); 
71.    pthread_join(thread2,&result); 
72. 
73.    //关闭线程,释放资源  
74.    pthread_attr_destroy(&attr1); 
75.    pthread_attr_destroy(&attr2); 
76. 
77.    cout<<"the g_counter = "<<g_counter<<endl; 
78. 
79.    int iWait; 
80.    cin>>iWait; 
81. 
82.    return 0; 
83.} 
// pthread_rwlock.cpp : 定义控制台应用程序的入口点。
//

#include "RWLockImpl.h"

//创建一个读写锁对象
CMyRWLock g_myRWLock;
volatile int g_counter = 0;

//线程函数
void * StartThread(void *pParam)
{
 int lastCount = 0;
 for (int i = 0; i < 10000; ++i)
 {
  g_myRWLock.ReadLock();
  lastCount = g_counter;
  //在读锁域,两个线程不断循环交替访问全局变量g_counter
  for (int k = 0; k < 100; ++k)
  {
   if (g_counter != lastCount)
    cout<<"the value of g_counter has been updated."<<endl;
   sleep(0);
  }
  g_myRWLock.Unlock();


  g_myRWLock.WriteLock();
  //在写锁域,只有一个线程可以修改全局变量g_counter的值
  for (int k = 0; k < 100; ++k)
  {
   --g_counter;
   sleep(0);
  }
  for (int k = 0; k < 100; ++k)
  {
   ++g_counter;
   sleep(0);
  }
  ++g_counter;
  if (g_counter <= lastCount)
   cout<<"the value of g_counter is error."<<endl;
  g_myRWLock.Unlock();
 }

 return (void *)0;
}

int main(int argc, char* argv[])
{
 pthread_t thread1,thread2;
 pthread_attr_t attr1,attr2;

 //创建两个工作线程
 pthread_attr_init(&attr1);
 pthread_attr_setdetachstate(&attr1,PTHREAD_CREATE_JOINABLE);
 if (pthread_create(&thread1,&attr1, StartThread,0) == -1)
 {
  cout<<"Thread 1: create failed"<<endl;
 }
 pthread_attr_init(&attr2);
 pthread_attr_setdetachstate(&attr2,PTHREAD_CREATE_JOINABLE);
 if (pthread_create(&thread2,&attr2, StartThread,0) == -1)
 {
  cout<<"Thread 2: create failed"<<endl;
 }

 //等待线程结束
 void *result;
 pthread_join(thread1,&result);
 pthread_join(thread2,&result);

 //关闭线程,释放资源
 pthread_attr_destroy(&attr1);
 pthread_attr_destroy(&attr2);

 cout<<"the g_counter = "<<g_counter<<endl;

 int iWait;
 cin>>iWait;

 return 0;
}
    编译,运行

 


    运行结果与在Win32下用C++实现多线程读写锁的相同。

 

// 一个Windows下C++读写锁的代码,实现共享读,独占写

class ReadWriteLock
{
public:
    int    m_currentLevel;
    int    m_readCount;  
    HANDLE m_unlockEvent;
    HANDLE m_accessMutex;
    CRITICAL_SECTION m_csStateChange;
public:
    ReadWriteLock()
    {
        m_currentLevel = LOCK_LEVEL_NONE;
        m_readCount    = 0;
        m_unlockEvent  = ::CreateEvent( NULL, TRUE, FALSE, NULL );
        m_accessMutex  = ::CreateMutex( NULL, FALSE, NULL );
        ::InitializeCriticalSection( &m_csStateChange );
    }
    ~ReadWriteLock()
    {
        ::DeleteCriticalSection( &m_csStateChange );
        if ( m_accessMutex ) ::CloseHandle( m_accessMutex );
        if ( m_unlockEvent ) ::CloseHandle( m_unlockEvent );
    }

 bool lock( int level, int timeout = INFINITE)
    {
        bool  bresult    = true;
        DWORD waitResult = 0;
       
        waitResult = ::WaitForSingleObject( m_accessMutex, timeout );
        if ( waitResult != WAIT_OBJECT_0 )  return false;

        if ( level == LOCK_LEVEL_READ && m_currentLevel != LOCK_LEVEL_WRITE )
        {
            ::EnterCriticalSection( &m_csStateChange );
            m_currentLevel = level;
            m_readCount += 1;
            ::ResetEvent( m_unlockEvent );
            ::LeaveCriticalSection( &m_csStateChange );
        }
        else if ( level == LOCK_LEVEL_READ &&
                  m_currentLevel == LOCK_LEVEL_WRITE )
        {
            waitResult = ::WaitForSingleObject( m_unlockEvent, timeout );
            if ( waitResult == WAIT_OBJECT_0 )
            {
                ::EnterCriticalSection( &m_csStateChange );
                m_currentLevel = level;
                m_readCount += 1;
                ::ResetEvent( m_unlockEvent );
                ::LeaveCriticalSection( &m_csStateChange );
            }
            else bresult = false;
        }
        else if ( level == LOCK_LEVEL_WRITE &&
                  m_currentLevel == LOCK_LEVEL_NONE )
        {
            ::EnterCriticalSection( &m_csStateChange );
            m_currentLevel = level;
            ::ResetEvent( m_unlockEvent );
            ::LeaveCriticalSection( &m_csStateChange );
        }
        else if ( level == LOCK_LEVEL_WRITE &&
                  m_currentLevel != LOCK_LEVEL_NONE )
        {
            waitResult = ::WaitForSingleObject( m_unlockEvent, timeout );
            if ( waitResult == WAIT_OBJECT_0 )
            {
                ::EnterCriticalSection( &m_csStateChange );
                m_currentLevel = level;
                ::ResetEvent( m_unlockEvent );
                ::LeaveCriticalSection( &m_csStateChange );
            }
            else bresult = false;
        }

        ::ReleaseMutex( m_accessMutex );
        return bresult;

    } // lock()
   
 bool unlock()
    {
        ::EnterCriticalSection( &m_csStateChange );
        if ( m_currentLevel == LOCK_LEVEL_READ )
        {
            m_readCount --;
            if ( m_readCount == 0 )
            {
                m_currentLevel = LOCK_LEVEL_NONE;
                ::SetEvent (m_unlockEvent);
            }
        }
        else if ( m_currentLevel == LOCK_LEVEL_WRITE )
        {
            m_currentLevel = LOCK_LEVEL_NONE;
            ::SetEvent ( m_unlockEvent );
        }
        ::LeaveCriticalSection( &m_csStateChange );

        return true;
    }
}; 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值