在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
- #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();
- }
- #endif
- #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;
- }
下边是测试代码
- // 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;
- }