简述电子商务网站建设的基本流程,重庆企业网站建设价格,网站制作入门,企业管理系统免费版前一篇文章分析了Windows slim read/write lock的工作原理。我们知道它的设计相当精妙#xff0c;于是我们可以借鉴它的思路来设计linux下的读写锁。在这个读写锁的设计上#xff0c;需要注意的是linux和windows有以下几点区别#xff1a;(1)windows使用的keyedevent机制需要…前一篇文章分析了Windows slim read/write lock的工作原理。我们知道它的设计相当精妙于是我们可以借鉴它的思路来设计linux下的读写锁。在这个读写锁的设计上需要注意的是linux和windows有以下几点区别(1)windows使用的keyedevent机制需要使用linux下的机制代替。这里我们选用futex机制来模拟。linux下的futex机制对外表现为下面这个接口int futex(int *uaddr, int op, int val, const struct timespec *timeout, int *uaddr2, int val3)但是由于没有公开提供该接口所有我们需要使用syscall来调用它如下#define futex(addr1, op, val, rel, addr2, val3) \syscall(SYS_futex, addr1, op, val, rel, addr2, val3)#define futex_wait_always(addr1) \syscall(SYS_futex, addr1, FUTEX_WAIT, *(int*)(addr1), 0, 0, 0)#define futex_wake_single(addr1) \syscall(SYS_futex, addr1, FUTEX_WAKE, 1, 0, 0, 0)在这里我们主要使用单个线程死等和唤醒单个线程两项操作。关于futex的其他知识可以参考搜索引擎不再赘述。(2)futex的wake机制和KeyedEvent有所区别。NtReleaseKeyedEvent唤醒等待线程时如果此时尚不存在等待者NtReleaseKeyedEvent会阻塞直到有等待者出现。但是通过在linux环境 “Linux version 3.2.0-23-generic (gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu4) ) #36-Ubuntu SMP Tue Apr 10 20:39:51 UTC 2012 ”下 的测试FUTEX_WAKE在没有等待者的情况下任然会直接返回不会等待于是采用的下面的代码模拟NtReleaseKeyedEvent。要注意到FUTEX_WAKE的返回值是实际唤醒线程的个数while(1 ! (futex_wake_single(tmp2))){unsigned int n 0;RtlBackoff(n);}(3)linux下的_mm_pause并不是真的调用了cpu的pause指令而是用nop指令代替这和VC的编译结果是不一样的因此需要实现一个自己的__mm_pause:__inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))__mm_pause (void){__asm__ __volatile__ (pause : : :memory);}(4)关于函数局部变量要对齐到16字节的问题在现在新版本的gcc编译环境下可以不考虑gcc默认是对齐到16字节的。当然也可以指定函数属性如下void __attribute__((force_align_arg_pointer)) RtlAcquireSRWLockExclusive(SRWLOCK* pSRWLock);void __attribute__((force_align_arg_pointer)) RtlAcquireSRWLockShared(SRWLOCK* pSRWLock);(5)VC提供的interlockedXXX系列函数相当丰富需要使用gcc提供的__syncXXXX系列的十来个函数来代替相当蛋疼。由于原生态的读写锁CRWLock不支持同一线程的递归锁操作所有增加了一个CRWLockRecur类其中记录了线程id用于实现递归锁功能。CRWLock类的代码经过了30个线程1.5亿次随机加解锁操作测试能够稳定工作。好了下面贴出头文件部分代码完整代码比较长就不贴了可以到http://download.csdn.net/detail/yichigo/7603735下载参考完全免费。欢迎指正#ifndef __RW_LOCK_H__#define __RW_LOCK_H__#if defined(_WIN32) || defined(WIN32) || defined(_WIN64)#if !defined(RWL_WINDOWS)#define RWL_WINDOWS#endif // WIN32 or _WIN32#elif defined(__linux__) || defined(__linux)#if !defined(RWL_LINUX)#define RWL_LINUX#endif#endif // not RWL_WINDOWS#ifdef RWL_WINDOWS#include #else#include #include #include #include #include #include #endif#ifdef RWL_WINDOWS#if !defined(ASSERT)#define ASSERT(f) ((f) || (__debugbreak(),0))#endif#else /// linux#define ASSERT assert//// int futex(int *uaddr, int op, int val, const struct timespec *timeout, int *uaddr2, int val3);#define futex(addr1, op, val, rel, addr2, val3) \syscall(SYS_futex, addr1, op, val, rel, addr2, val3)#define futex_wait_always(addr1) \syscall(SYS_futex, addr1, FUTEX_WAIT, *(int*)(addr1), 0, 0, 0)#define futex_wake_single(addr1) \syscall(SYS_futex, addr1, FUTEX_WAKE, 1, 0, 0, 0)//// linux下的_mm_pause不是真正的pause// 自己实现一个__inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))__mm_pause (void){__asm__ __volatile__ (pause : : :memory);}#define SRWLockSpinCount 1024#define Busy_Lock1// 已经有人获取了锁#define Wait_Lock2// 有人等待锁#define Release_Lock4// 说明已经有人释放一次锁#define Mixed_Lock8// 共享锁、独占锁并存#define EXTRACT_ADDR(s)((s) (~0xf)) // 去掉低4位#endif#ifdef RWL_WINDOWSclass CRWLock{public:CRWLock();~CRWLock();void ExclusiveLock();void SharedLock();void ReleaseExclusiveLock();void ReleaseSharedLock();private:SRWLOCK m_SRWLock;};#else /// linuxclass CRWLock{struct SRWLOCK {size_t Ptr;};struct _SyncItem{int ifutex;_SyncItem* back;_SyncItem* notify;_SyncItem* next;size_t shareCount;size_t flag;};public:CRWLock();~CRWLock();void ExclusiveLock();void SharedLock();void ReleaseExclusiveLock();void ReleaseSharedLock();private:void RtlInitializeSRWLock(SRWLOCK* pSRWLock);void __attribute__((force_align_arg_pointer)) RtlAcquireSRWLockExclusive(SRWLOCK* pSRWLock);void __attribute__((force_align_arg_pointer)) RtlAcquireSRWLockShared(SRWLOCK* pSRWLock);void RtlReleaseSRWLockExclusive(SRWLOCK* pSRWLock);void RtlReleaseSRWLockShared(SRWLOCK *pSRWLock);void RtlpWakeSRWLock(SRWLOCK* pSRWLock, size_t st);void RtlBackoff(unsigned int *pCount);void RtlpOptimizeSRWLockList(SRWLOCK* pSRWLock, size_t st);private:SRWLOCK m_SRWLock;};#endif////// 增加一个获取独占锁线程id记录// 实现独占锁递归支持//class CRWLockRecur : public CRWLock{public:CRWLockRecur(){m_tid -1;m_nRecursion 0;}~CRWLockRecur(){}void OwnLock(){if (m_tid ! GetTid()){ExclusiveLock();m_tid GetTid();}m_nRecursion;}void ShareLock(){SharedLock();}void UnOwnLock(){m_nRecursion--;if (0 m_nRecursion){m_tid 0;ReleaseExclusiveLock();}}void UnShareLock(){ReleaseSharedLock();}private:size_t GetTid(){#ifdef RWL_WINDOWSreturn GetCurrentThreadId();#elsereturn pthread_self();#endif}private:size_t m_tid;unsigned int m_nRecursion;};#endif