1. 程式人生 > >一種跨平臺的快速鎖

一種跨平臺的快速鎖

    C++11釋出了四種不同的用於跨平臺的鎖,但其為了誇平臺做了很多工作,在需要效能要求的情況下,大量的呼叫枷鎖解鎖必定會導致效率問題(現在計算機都這麼快了這點運算其實又算得了什麼呢,以後就不拿效能當幌子了閉嘴),實際上在C++11釋出之前就寫好了一個誇平臺的鎖(大部分平臺都可以用),程式碼比較簡潔可以直接拿來用,自己平時用的比較多,真正原因就是自己不捨得這些程式碼用C++11的代替了。


    這裡要介紹的鎖在同線程下支援遞迴枷鎖,windows下使用臨界區,不涉及核心物件,其他平臺使用pthread庫中的pthread_mutex_t物件,含有PTHREAD_MUTEX_RECURSIVE屬性實現歸枷鎖,程式碼分了兩個檔案來實現,分別貼上在下面,其中#include "PLTConfig.h"檔案中定義了一些系統巨集,參考QT定義的系統巨集。

這是.h檔案

/* 
============================================================================================
	Locker 快速鎖物件
	同線程內可以遞迴加鎖
	加鎖和解鎖必須在同一執行緒內
	這種鎖是程序內私有 不能和其他程序公用
	windows下使用臨界區 pthread下使用PTHREAD_MUTEX_RECURSIVE屬性的互斥量

	add 2013.11.22 by yuwf

	Copyright (c), ...	

=============================================================================================
*/

#ifndef _PALANTIR_LOCKER_H
#define _PALANTIR_LOCKER_H

#include "PLTConfig.h"	// 根據系統定義 PLT_OS_WIN 和 PTHREAD 巨集

#if defined(PLT_OS_WIN)
#include <windows.h>
#elif defined(PTHREAD)
#include <pthread.h>
#endif

namespace Palantir
{
	// 允許加鎖執行緒遞迴加鎖
	class Locker
	{
	public:
		Locker();
		~Locker();

		// 加鎖 不是同一執行緒枷鎖會阻塞
		void Lock();

		// 非阻塞 枷鎖成功返回true 否則返回false
		bool TryLock();

		// 解鎖
		void Unlock();

	protected:
#if defined(PLT_OS_WIN)
		CRITICAL_SECTION	m_critical_section;	// 臨界區
#elif defined(PTHREAD)
		pthread_mutex_t 	m_mutex;			// 互斥鎖
#endif

	private:
		// 禁止拷貝和賦值構造
		Locker( const Locker& ) {};
		Locker& operator = ( const Locker& ) { return *this; };
	};

	// 空鎖 輔助使用
	class EmptyLocker
	{
	public:
		// 加鎖
		void Lock() {};

		bool TryLock() { return true; };

		// 解鎖
		void Unlock() {};
	};
	
	// 加鎖輔助工具
	template<class _LockerType_>
	class LockerGuard
	{
	public:
		LockerGuard( _LockerType_& locker ) 
			: m_locker(locker)
		{
			locker.Lock();
		}
		~LockerGuard()
		{
			m_locker.Unlock();
		}
	protected:
		_LockerType_& m_locker;
	};

	typedef LockerGuard<Locker> AutoLocker;
	
}

#endif


這是.cpp檔案

/* 
============================================================================================
	Locker 快速鎖物件 實現檔案

	add 2013.11.22 by yuwf

	Copyright (c), ...	

=============================================================================================
*/


#include "PLTLocker.h"

namespace Palantir
{
	Locker::Locker()
	{
#if defined(PLT_OS_WIN)
		InitializeCriticalSection( &m_critical_section );
#elif defined(PTHREAD)
		pthread_mutexattr_t attr;
		pthread_mutexattr_init( &attr );
		pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );	// 這個互斥鎖可遞迴加鎖 因為windows下的臨界區可以遞迴加鎖
		pthread_mutex_init( &m_mutex, &attr );
#endif
	}

	Locker::~Locker()
	{
#if defined(PLT_OS_WIN)
		DeleteCriticalSection( &m_critical_section );
#elif defined(PTHREAD)
		pthread_mutex_destroy( &m_mutex );
#endif
	}

	void Locker::Lock()
	{
#if defined(PLT_OS_WIN)
		EnterCriticalSection( &m_critical_section );
#elif defined(PTHREAD)
		pthread_mutex_lock( &m_mutex );
#endif
	}

	bool Locker::TryLock()
	{
#if defined(PLT_OS_WIN)
		if ( !TryEnterCriticalSection( &m_critical_section ) )
		{
			return false;
		}
#elif defined(PTHREAD)
		if( pthread_mutex_trylock( &m_mutex ) != 0 )
		{
			return false;
		}
#endif
		return true;
	}

	void Locker::Unlock()
	{
#if defined(PLT_OS_WIN)
		LeaveCriticalSection( &m_critical_section );
#elif defined(PTHREAD)
		pthread_mutex_unlock( &m_mutex );
#endif
	}
}



程式碼中定義了一個空鎖EmptyLocker,主要用來輔助使用,比如在後面要介紹的記憶體池中可以傳入一個空鎖來實現一個不需要枷鎖的記憶體池,LockerGuard也是用來輔助使用,功能很簡單,不做贅述。

相關推薦

跨平臺快速

    C++11釋出了四種不同的用於跨平臺的鎖,但其為了誇平臺做了很多工作,在需要效能要求的情況下,大量的呼叫枷鎖解鎖必定會導致效率問題(現在計算機都這麼快了這點運算其實又算得了什麼呢,以後就不拿效能當幌子了),實際上在C++11釋出之前就寫好了一個誇平臺的鎖(大部分平

數據庫查詢速度慢了?是否是因為死了?解決死的方法。

-- 檢索 blog kill _id exe 進行 xxx 通過 --查詢哪些表被死鎖 select request_session_id spid,OBJECT_NAME(resource_associated_entity_id) tableName from sy

高效無記憶體佇列的實現

Disruptor是LMAX公司開源的一個高效的記憶體無鎖佇列。這兩天看了一下相關的設計文件和部落格,下面嘗試進行一下總結。 第一部分。引子 談到併發程式設計,有幾個概念是避免不了的。 1.鎖:鎖是用來做併發最簡單的方式,當然其代價也是最高的。核心態的鎖的時候需要作業

粗暴快速的Android全螢幕適配方案

熱文導讀 | 點選標題閱讀作者:firedamp來源:http://www.apkbus.com

[Android] 粗暴快速的 Android 全螢幕適配方案

1 現狀 由於Android碎片化嚴重,螢幕適配一直是開發中較為頭疼的問題。面對市面上五花八門的螢幕大小與解析度,Android基於dp與res目錄名稱來適配的方案已無法滿足一次編寫全螢幕適配的需求,為了達到最優的視覺效果,開發過程中總是需要花費較多資源進行適配。也有開

粗暴快速的解決mysql主從不同步錯誤的思路

通過 大量 word mysql 影響 簡單 posit code change mysql主從經常會出現主從數據不同步的問題,臟數據會造成主從同步中斷, 出現大量ERROR,如1032,1062等錯誤。常規方法是逐條刪除臟數據或者 重做

簡單的跨平臺使用者態自旋

   自旋鎖作為一種併發同步的手段,特別適用於競爭少和鎖時間短的情況,在驅動及核心程式碼中經常被用到,本文講述一種適合使用者態程式的自旋鎖,支援Windows和Linux(GCC>=4.1.2)平臺,並提供了C語言的介面和實現。 介面   spin_trylock如果獲取成功返回1,否

簡單的跨平臺互斥

   互斥鎖,用來保證任一時刻只有單個執行緒或程序擁有對共享資源的互斥訪問權,在這裡將posix thread中的互斥體、win32中的互斥體和臨界區,統稱為互斥鎖,其特點如下:   ● 範圍:執行緒鎖和程序鎖,前者僅用於同一程序內多執行緒間,而後者用於程序間,顯然,它也能用於同一程序內多執行緒間

安洛克智能:經常忘記帶鑰匙是

安洛克智能鎖 前不久,廣西一位年過六旬的阿婆,忘帶鑰匙回不了家了,而自己又舍不得80元請鎖匠,所以找來了繩子把自己五花大綁的,打算從樓頂往下吊,想不到的是,卻被懸空吊在了三到四樓之間,動彈不得,還嚇出了一身冷汗,還好消防官兵及時趕到,第一時間把阿婆救下。 其實這已經不是什麽新鮮的事了,很多人明明知

排序_快速排序_另取劃分點的方法

交換 ++ new 改進 break value 進行 ins man 最基本的劃分點由數組的最後一個值來確定,現在是將數組的最後一個值的前一個數值作為劃分點,但是需要經過三項取一方法的變換,最後它位置上的值是三個中最大的。 public class ArrayIns {

基於redis的分布式

thread 語法 客戶端 read not end 過程 == 直接 前言:本文介紹了一種基於redis的分布式鎖,利用jedis實現應用(本文應用於多客戶端+一個redis的架構,並未考慮在redis為主從架構時的情況) 文章理論來源部分引自:https://i.cnb

python全棧開發基礎【第二十篇】互斥以及進程之間的三通信方式(IPC)以及生產者個消費者模型

ipc 例子 清空 ase 多個進程 art 並且 star als 一、互斥鎖 進程之間數據隔離,但是共享一套文件系統,因而可以通過文件來實現進程直接的通信,但問題是必須自己加鎖處理。 註意:加鎖的目的是為了保證多個進程修改同一塊數據時,同一時間只能有一個修改,即串行的修

樂觀實現方式——CAS

www. 提升 中一 num 對象 用戶 ace 另一個 nbsp 原文出處: hollischuang (@Hollis_Chuang) 在深入理解樂觀鎖與悲觀鎖一文中我們介紹過鎖。本文在這篇文章的基礎上,深入分析一下樂觀鎖的實現機制,介紹什麽是CAS、CAS的應用以及C

遊戲編程精粹學習 - 快速的圓柱棱臺相交測試算法

AD pos ali invisible isp using 左右 () OS 掛載Renderer的對象可以使用OnBecameVisible/OnBecameInvisible來接收剔除事件。 但是非Renderer對象則要自己處理相交檢測。 文中的方法測試結

Java並發問題--樂觀與悲觀以及樂觀實現方式-CAS

RF -- 指針 locking water 更多 錯誤 創建 判斷 首先介紹一些樂觀鎖與悲觀鎖: 悲觀鎖:總是假設最壞的情況,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會阻塞直到它拿到鎖。傳統的關系型數據庫裏邊就用到了很多這

【科技】原根的快速判斷方法以及對1求離散對數的另想法

鑑於實際需要,本文中所選的模數$p$總是一個平凡質數,並用$\phi$表示$\phi (p) = p - 1$。 原根的定義: 基於$p$是質數,我們可以很簡單的把它的定義想成,如果一個數$a \in [0, p - 1]$是原根的充要條件是對於$x \in [0, p - 2]$,$a^{x}$互不相同

Android 快速檢視SH1和MD5的另便捷方法

@echo off set keyPath="%1" "%JAVA_HOME%\bin\keytool" -list -v -keystore %keyPath% pause 使用方法:複製此段程式碼,新建文字檔案並貼上到這裡,檔名字尾改為.bat,把你的簽名檔案拖動到剛剛新建的那個.bat檔案

快速卷積實現方法

本文基於論文Fast Algorithms for Convolutional Neural Networks,並且整理了相關知識點。 我們首先了解一下傅立葉變換: 對於連續型傅立葉變換的頻域核時域轉換公式: 對於離散的傅立葉變換: 關於傅立葉的理解 可以看這篇文章

java實現快速排序常規的,是左程雲的方式。

java實現快速排序: 一:先來一個常規快排: 這個方式就是我們的基準值一直在兩個邊界徘徊,要麼在less的較大邊界,要麼是在more的小邊界,其實就是在居中位置徘徊。 package chapter1; //來一個快排,常規快排 public class QuickSort {

往Excel中快速寫入數據的又方法

fps fas framework 導出到excel object targe star 列名 num 往Excel寫入數據的方法比較多,但實際應用場景及對性能的要求決定了需要對方法有所取舍。一些具體情形和方法可以參見https://blog.csdn.net/u01310