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 plain copy
  1. #ifndef _RWLockImpl_Header  
  2. #define _RWLockImpl_Header  
  3.   
  4. #include <iostream>  
  5. #include <pthread.h>  
  6. #include <errno.h>  
  7. #include <assert.h>  
  8.   
  9. 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  
RWLockImpl.cpp

[cpp]  view plain copy
  1. #include "RWLockImpl.h"  
  2.   
  3. CRWLockImpl::CRWLockImpl()  
  4. {  
  5.     if (pthread_rwlock_init(&m_rwl, NULL))  
  6.         cout<<"cannot create reader/writer lock"<<endl;  
  7. }  
  8.   
  9. 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. }  

    下边是测试代码

[cpp]  view plain copy
  1. // pthread_rwlock.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "RWLockImpl.h"  
  5.   
  6. //创建一个读写锁对象  
  7. CMyRWLock g_myRWLock;  
  8. volatile int g_counter = 0;  
  9.   
  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. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux线程服务端编程是指使用Muduo C网络库在Linux操作系统中进行多线程的服务端编程。Muduo C网络库是一个基于事件驱动的网络库,采用了Reactor模式,并且在底层使用了epoll来实现高效的I/O复用。 使用Muduo C网络库进行多线程服务端编程有以下几个步骤: 1. 引入Muduo C网络库:首先需要下载并引入Muduo C网络库的源代码,然后在编写代码时包含相应的头文件。 2. 创建并初始化EventLoop:首先需要创建一个EventLoop对象,它用于接收和分发事件。通过初始化函数进行初始化,并在主线程中调用它的loop()函数来运行事件循环。 3. 创建TcpServer:然后创建一个TcpServer对象,它负责监听客户端的连接,并管理多个TcpConnection对象。通过设置回调函数,可以在特定事件发生时处理相应的逻辑。 4. 创建多个EventLoopThread:为了提高并发性能,可以创建多个EventLoopThread对象,每个对象负责一个EventLoop,从而实现多线程处理客户端的连接和请求。 5. 处理事件:在回调函数中处理特定事件,例如有新的连接到来时会调用onConnection()函数,可以在该函数中进行一些初始化操作。当有数据到来时会调用onMessage()函数,可以在该函数中处理接收和发送数据的逻辑。 6. 运行服务端:在主线程中调用TcpServer的start()函数来运行服务端,等待客户端的连接和请求。 总的来说,使用Muduo C网络库进行Linux线程服务端编程可以更好地利用多核处理器的性能优势。每个线程负责处理特定事件,通过事件驱动模式实现高效的网络编程。这样可以提高服务器的并发能力,提高系统的整体性能。 ### 回答2: Linux线程服务端编程是指在Linux平台上使用多线程的方式来编写网络服务器程序。而使用muduo C网络库是一种常见的方法,它提供了高效的网络编程接口,可以简化多线程服务器的开发过程。 muduo C网络库基于Reactor模式,利用多线程实现了高并发的网络通信。在使用muduo C进行多线程服务端编程时,我们可以按照以下步骤进行: 1. 引入muduo库:首先需要导入muduo C网络库的头文件,并链接对应的库文件,以供程序调用。 2. 创建线程池:利用muduo C中的ThreadPool创建一个线程池,用于管理和调度处理网络请求的多个线程。 3. 创建TcpServer对象:使用muduo C中的TcpServer创建一个服务器对象,监听指定的端口,并设置好Acceptor、TcpConnectionCallback等相关回调函数。 4. 定义业务逻辑:根据具体的业务需求,编写处理网络请求的业务逻辑代码,如接收客户端的请求、处理请求、发送响应等。 5. 注册业务逻辑函数:将定义好的业务逻辑函数注册到TcpServer对象中,以便在处理网络请求时调用。 6. 启动服务器:调用TcpServer对象的start函数,启动服务器,开始监听端口并接收客户端请求。 7. 处理网络请求:当有客户端连接到服务器时,muduo C会自动分配一个线程去处理该连接,执行注册的业务逻辑函数来处理网络请求。 8. 释放资源:在程序结束时,需要调用相应的函数来释放使用的资源,如关闭服务器、销毁线程池等。 通过使用muduo C网络库,我们可以简化多线程服务端编程的过程,提高服务器的并发处理能力。因为muduo C网络库已经实现了底层的网络通信细节,我们只需要专注于编写业务逻辑代码,从而减少开发的工作量。同时,muduo C的多线程模型可以有效地提高服务器的并发性能,满足高并发网络服务的需求。 ### 回答3: Linux线程服务端编程是指在Linux操作系统上开发多线程的服务器应用程序。使用muduo C网络库有助于简化开发过程,提供高效的网络通信能力。 muduo C网络库是一个基于Reactor模式的网络库,适用于C++语言,由Douglas Schmidt的ACE网络库演化而来。它提供了高度并发的网络编程能力,封装了许多底层细节,使得开发者能够更加专注于业务逻辑的实现。 在开发过程中,首先需要创建一个muduo C的EventLoop对象来管理事件循环。然后,可以利用TcpServer来创建服务器并监听指定的端口。当有新的客户端请求到达时,muduo C会自动调用用户定义的回调函数处理请求。 在处理请求时,可以使用muduo C提供的ThreadPool来创建多个工作线程。这些工作线程将负责处理具体的业务逻辑。通过将工作任务分配给不同的线程,可以充分利用多核服务器的计算资源,提高服务器的处理能力。 在具体的业务逻辑中,可以使用muduo C提供的Buffer来处理网络数据。Buffer提供了高效的数据读写操作,可以方便地进行数据解析与封装。 此外,muduo C还提供了TimerQueue来处理定时任务,可以用于实现定时事件的调度与管理。这对于一些需要定期执行的任务非常有用,如心跳检测、定时备份等。 总之,使用muduo C网络库可以简化Linux线程服务端编程的开发过程,提供高效的并发能力。通过合理地利用多线程和其他的相关组件,可以实现高性能、稳定可靠的网络服务端应用程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值