日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux 进程 读写锁,linux 下实现高性能读写锁(read/write lock)

發布時間:2025/3/11 linux 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux 进程 读写锁,linux 下实现高性能读写锁(read/write lock) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前一篇文章分析了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_WINDOWS

class CRWLock

{

public:

CRWLock();

~CRWLock();

void ExclusiveLock();

void SharedLock();

void ReleaseExclusiveLock();

void ReleaseSharedLock();

private:

SRWLOCK m_SRWLock;

};

#else /// linux

class 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_WINDOWS

return GetCurrentThreadId();

#else

return pthread_self();

#endif

}

private:

size_t m_tid;

unsigned int m_nRecursion;

};

#endif

總結

以上是生活随笔為你收集整理的linux 进程 读写锁,linux 下实现高性能读写锁(read/write lock)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。