freeswitch APR庫執行緒讀寫鎖
概述
freeswitch的核心源程式碼是基於apr庫開發的,在不同的系統上有很好的移植性。
執行緒讀寫鎖在多執行緒服務中有重要的作用。對於讀數據比寫數據頻繁的服務,用讀寫鎖代替互斥鎖可以提高效率。
由於APR庫是跨平台的,而不同平台上的系統介面有區別,所以在APR庫中就有一個適配層目錄libs\apr\include\arch\,該目錄下有不同系統的頭文件定義,包括aix、beos、netware、os2、os390、unix、win32。
在編譯源程式碼文件的過程中,根據當前系統自動選擇不同的文件目錄來適配。
下面我們對apr庫的執行緒讀寫鎖實現做一個介紹。
環境
centos:CentOS release 7.0 (Final)或以上版本
freeswitch:v1.8.7
GCC:4.8.5
讀寫鎖數據結構
apr庫的執行緒讀寫鎖源程式碼文件在libs/apr目錄下,這裡只列出了unix和win32的版本。
libs\apr\include\apr_thread_rwlock.h
libs\apr\include\arch\unix\apr_arch_thread_rwlock.h
libs\apr\locks\unix\thread_rwlock.c
libs\apr\include\arch\win32\apr_arch_thread_rwlock.h
libs\apr\locks\win32\thread_rwlock.c
讀寫鎖結構體定義。
我們可以看出,在unix系統下直接使用了pthread執行緒庫的讀寫鎖實現。
libs\apr\include\arch\unix\apr_arch_thread_rwlock.h
struct apr_thread_rwlock_t {
apr_pool_t *pool;
pthread_rwlock_t rwlock;
};
在win32系統則是使用了臨界區CRITICAL_SECTION、mutex和event協同實現。
libs\apr\include\arch\win32\apr_arch_thread_rwlock.h
struct apr_thread_rwlock_t {
apr_pool_t *pool;
HANDLE write_mutex;
HANDLE read_event;
LONG readers;
CRITICAL_SECTION read_section;
};
常用函數
查看源程式碼頭文件libs\apr\include\apr_thread_rwlock.h。
apr_thread_rwlock_create //創建並初始化1個執行緒讀寫鎖
apr_thread_rwlock_rdlock //獲取1個共享讀鎖
apr_thread_rwlock_tryrdlock //非阻塞獲取1個共享讀鎖
apr_thread_rwlock_wrlock //獲取1個獨佔寫鎖
apr_thread_rwlock_trywrlock //非阻塞獲取1個獨佔寫鎖
apr_thread_rwlock_unlock //解鎖1個讀寫鎖
apr_thread_rwlock_destroy //銷毀讀寫鎖
從介面定義我們可以看出,加讀鎖和加寫鎖是分開的介面,而解鎖是同一個介面。
介面的實現我們簡單介紹一下。
在unix系統下,讀寫鎖的介面中直接調用了pthread庫中對應的讀寫鎖介面。
比如apr_thread_rwlock_create中調用了pthread_rwlock_init,apr_thread_rwlock_rdlock中調用了pthread_rwlock_rdlock等等,這裡就不再詳細展開了,有興趣的可以自己查看一下pthread_rwlock_t讀寫鎖的定義和實現。
在win32系統下,讀寫鎖的介面中使用了readers、read_event、write_mutex和read_section幾個變數共同實現了讀寫鎖的功能。
偽程式碼-讀鎖(讀寫鎖, 超時時間)
進入臨界區read_section
等待訊號write_mutex,失敗或超時則返回錯誤
計數器readers+1
重置事件read_event,失敗則返回錯誤
釋放write_mutex,失敗則返回錯誤
離開臨界區read_section
返回成功
偽程式碼-寫鎖(讀寫鎖, 超時時間)
等待訊號write_mutex,失敗或超時則返回錯誤
等待訊號read_event,失敗或超時則釋放write_mutex,並返回錯誤
返回成功
偽程式碼-解鎖(讀寫鎖)
釋放write_mutex
計數器readers-1
設置事件read_event
返回
說實話。。。win32的程式碼我沒看懂,有沒有win開發的高手給講解一下。
比如,為什麼只有讀鎖中有臨界區read_section的操作,為什麼write_mutex只有釋放操作,為什麼寫鎖中沒有等待readers為0。。。
總結
apr庫的執行緒讀寫鎖的實現介紹完了。
讀寫鎖的適用場景是多執行緒下讀多寫少的業務流程,以實現獨佔寫和共享讀的邏輯。
在合適的場景中,讀寫鎖比互斥鎖有更高的並發能力和效率。
另外,還有強讀者和強寫者倆種不同的形式,讀者可以自己深入研究一下。
空空如常
求真得真