青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 17,comments - 7,trackbacks - 0

(作者:Douglas C. Schmidt ,by huihoo.org CORBA課題 Thzhang 譯 , Allen整理,制作)

意圖

無論什么時候當臨界區(qū)中的代碼僅僅需要加鎖一次,同時當其獲取鎖的時候必須是線程安全的,可以用Double Checked Locking 模式來減少競爭和加鎖載荷。

動機

1、標準的單例。開發(fā)正確的有效的并發(fā)應(yīng)用是困難的。程序員必須學習新的技術(shù)(并發(fā)控制和防止死鎖的算法)和機制(如多線程和同步API)。此外,許多熟悉的設(shè)計模式(如單例和迭代子)在包含不使用任何并發(fā)上下文假設(shè)的順序程序中可以工作的很好。為了說明這點,考慮一個標準的單例模式在多線程環(huán)境下的實現(xiàn)。單例模式保證一個類僅有一個實例同時提供了全局唯一的訪問這個實例的入口點。在c++程序中動態(tài)分配單例對象是通用的方式,這是因為c++程序沒有很好的定義靜態(tài)全局對象的初始化次序,因此是不可移植的。而且,動態(tài)分配避免了單例對象在永遠沒有被使用情況下的初始化開銷。


class Singleton
{
public:
static Singleton *instance (void)
{
if (instance_ == 0)
// Critical section.
instance_ = new Singleton;
return instance_;
}
void method (void);
// Other methods and members omitted.
private:
static Singleton *instance_;
};


應(yīng)用代碼在使用單例對象提供的操作前,通過調(diào)用靜態(tài)的instance方法來獲取單例對象的引用,如下所示:
Singleton::instance ()->method ();
2、問題:競爭條件。不幸的是,上面展示的標準單例模式的實現(xiàn)在搶先多任務(wù)和真正并行環(huán)境下無法正常工作。例如,如果在并行主機上運行的多個線程在單例對象初始化之前同時調(diào)用Singleton::instance方法,Singleton的構(gòu)造函數(shù)將被調(diào)用多次,這是因為多個線程將在上面展示的臨界區(qū)中執(zhí)行new singleton操作。臨界區(qū)是一個必須遵守下列定式的指令序列:當一個線程/進程在臨界區(qū)中運行時,沒有其他任何線程/進程會同時在臨界區(qū)中運行。在這個例子中,單例的初始化過程是一個臨界區(qū),違反臨界區(qū)的原則,在最好的情況下將導(dǎo)致內(nèi)存泄漏,最壞的情況下,如果初始化過程不是冪等的(idempotent.),將導(dǎo)致嚴重的后果。

3、 通常的陷阱和弊端。實現(xiàn)臨界區(qū)的通常方法是在類中增加一個靜態(tài)的Mutex對象。這個Mutex保證單例的分配和初始化是原子操作,如下:


class Singleton
{
public:
static Singleton *instance (void)
{
// Constructor of guard acquires lock_ automatically.
Guard guard (lock_);
// Only one thread in the critical section at a time.
if (instance_ == 0)
instance_ = new Singleton;
return instance_;
// Destructor of guard releases lock_ automatically.
}
private:
static Mutex lock_;
static Singleton *instance_;
};


guard類使用了一個c++的習慣用法,當這個類的對象實例被創(chuàng)建時,它使用構(gòu)造函數(shù)來自動獲取一個資源,當類對象離開一個區(qū)域時,使用析構(gòu)器來自動釋放這個資源。通過使用guard,每一個對Singleton::instance方法的訪問將自動的獲取和釋放lock_。
即使這個臨界區(qū)只是被使用了一次,但是每個對instance方法的調(diào)用都必須獲取和釋放lock_。雖然現(xiàn)在這個實現(xiàn)是線程安全的,但過多的加鎖負載是不能被接受的。一個明顯(雖然不正確)的優(yōu)化方法是將guard放在針對instance進行條件檢測的內(nèi)部:


static Singleton *instance (void)
{
if (instance_ == 0) {
Guard guard (lock_);
// Only come here if instance_ hasn't been initialized yet.
instance_ = new Singleton;
}
return instance_;
}

這將減少加鎖負載,但是不能提供線程安全的初始化。在多線程的應(yīng)用中,仍然存在競爭條件,將導(dǎo)致多次初始化instance_。例如,考慮兩個線程同時檢測 instance_ == 0,都將會成功,一個將通過guard獲取lock_另一個將被阻塞。當?shù)谝痪€程初始化Singleton后釋放lock_,被阻塞的線程將獲取lock_,錯誤的再次初始化Singleton。
4、解決之道,Double Checked Locking優(yōu)化。解決這個問題更好的方法是使用Double Checked Locking。它是一種用于清除不必要加鎖過程的優(yōu)化模式。具有諷刺意味的是,它的實現(xiàn)幾乎和前面的方法一樣。通過在另一個條件檢測中包裝對new的調(diào)用來避免不必要的加鎖:


class Singleton
{
public:
static Singleton *instance (void)
{
// First check
if (instance_ == 0)
{
// Ensure serialization (guard constructor acquires lock_).
Guard guard (lock_);
// Double check.
if (instance_ == 0)
instance_ = new Singleton;
}
return instance_;
// guard destructor releases lock_.
}
private:
static Mutex lock_;
static Singleton *instance_;
};


第一個獲取lock_的線程將構(gòu)建Singleton,并將指針分配給instance_,后續(xù)調(diào)用instance方法的線程將發(fā)現(xiàn)instance_ != 0,于是將跳過初始化過程。如果多個線程試圖并發(fā)初始化Singleton,第二個檢測件阻止競爭條件的發(fā)生。在上面的代碼中,這些線程將在lock_上排隊,當排隊的線程最終獲取lock_時,他們將發(fā)現(xiàn)instance_ != 0于是將跳過初始化過程。

上面Singleton::instance的實現(xiàn)僅僅在Singleton首次被初始化時,如果有多個線程同時進入instance方法將導(dǎo)致加鎖負載。在后續(xù)對Singleton::instance的調(diào)用因為instance_ != 0而不會有加鎖和解鎖的負載。 通過增加一個mutex和一個二次條件檢測,標準的單例實現(xiàn)可以是線程安全的,同時不會產(chǎn)生過多的初始化加鎖負載。

適應(yīng)性

> 當一個應(yīng)用具有下列特征時,可以使用Double Checked Locking優(yōu)化模式:
1、應(yīng)用包含一個或多個需要順序執(zhí)行的臨界區(qū)代碼。
2、多個線程可能潛在的試圖并發(fā)執(zhí)行臨界區(qū)。
3、臨界區(qū)僅僅需要被執(zhí)行一次。
4、在每一個對臨界區(qū)的訪問進行加鎖操作將導(dǎo)致過多加鎖負載。
5、在一個鎖的范圍內(nèi)增加一個輕量的,可靠的條件檢測是可行的。

結(jié)構(gòu)和參與者

通過使用偽代碼能夠最好地展示Double Checked Locking模式的結(jié)構(gòu)和參與者,圖1展示了在Double Checked Locking模式有下列參與者:



1、僅有一次臨界區(qū)(Just Once Critical Section,)。臨界區(qū)所包含的代碼僅僅被執(zhí)行一次。例如,單例對象僅僅被初始化一次。這樣,執(zhí)行對new Singleton的調(diào)用(只有一次)相對于Singleton::instance方法的訪問將非常稀少。
2、mutex。鎖被用來序列化對臨界區(qū)中代碼的訪問。
3、標記。標記被用來指示臨界區(qū)的代碼是否已經(jīng)被執(zhí)行過。在上面的例子中單例指針instance_被用來作為標記。
4、 應(yīng)用線程。試圖執(zhí)行臨界區(qū)代碼的線程。

協(xié)作

圖2展示了Double Checked Locking模式的參與者之間的互動。作為一種普通的優(yōu)化用例,應(yīng)用線程首先檢測flag是否已經(jīng)被設(shè)置。如果沒有被設(shè)置,mutex將被獲取。在持有這個鎖之后,應(yīng)用線程將再次檢測flag是否被設(shè)置,實現(xiàn)Just Once Critical Section,設(shè)定flag為真。最后應(yīng)用線程釋放鎖。



 

結(jié)論

使用Double Checked Locking模式帶來的幾點好處:
1、最小化加鎖。通過實現(xiàn)兩個flag檢測,Double Checked Locking模式實現(xiàn)通常用例的優(yōu)化。一旦flag被設(shè)置,第一個檢測將保證后續(xù)的訪問不要加鎖操作。
2、防止競爭條件。對flag的第二個檢測將保證臨界區(qū)中的事件僅實現(xiàn)一次。
使用Double Checked Locking模式也將帶來一個缺點:產(chǎn)生微妙的移植bug的潛能。這個微妙的移植問題能夠?qū)е轮旅腷ug,如果使用Double Checked Locking模式的軟件被移植到?jīng)]有原子性的指針和正數(shù)賦值語義的硬件平臺上。例如,如果一個instance_指針被用來作為Singleton實現(xiàn)的flag,instance_指針中的所有位(bit)必須在一次操作中完成讀和寫。如果將new的結(jié)果寫入內(nèi)存不是一個原子操作,其他的線程可能會試圖讀取一個不健全的指針,這將導(dǎo)致非法的內(nèi)存訪問。
在一些允許內(nèi)存地址跨越對齊邊界的系統(tǒng)上這種現(xiàn)象是可能的,因此每次訪問需要從內(nèi)存中取兩次。在這種情況下,系統(tǒng)可能使用分離的字對齊合成flag,來表示instance_指針。
如果一個過于激進(aggressive)編譯器通過某種緩沖手段來優(yōu)化flag,或是移除了第二個flag==0檢測,將帶來另外的相關(guān)問題。后面會介紹如何使用volatile關(guān)鍵字來解決這個問題。

實現(xiàn)和例子代碼

ACE在多個庫組件中使用Double Checked Locking模式。例如,為了減少代碼的重復(fù),ACE使用了一個可重用的適配器ACE Singleton來將普通的類轉(zhuǎn)換成具有單例行為的類。下面的代碼展示了如何用Double Checked Locking模式來實現(xiàn)ACE Singleton。


// A Singleton Adapter: uses the Adapter
// pattern to turn ordinary classes into
// Singletons optimized with the
// Double-Checked Locking pattern.
template 
class ACE_Singleton
{
public:
static TYPE *instance (void);
protected:
static TYPE *instance_;
static LOCK lock_;
};
template  TYPE *
ACE_Singleton::instance ()
{
// Perform the Double-Checked Locking to
// ensure proper initialization.
if (instance_ == 0) {
ACE_Guard lock (lock_);
if (instance_ == 0)
instance_ = new TYPE;
}
return instance_;
}



ACE Singleton類被TYPE和LOCK來參數(shù)化。因此一個給定TYEP的類將被轉(zhuǎn)換成使用LOCK類型的互斥量的具有單例行為的類。
ACE中的Token Manager.是使用ACE Singleton的一個例子。Token Manager實現(xiàn)在多線程應(yīng)用中對本地和遠端的token(一種遞歸鎖)死鎖檢測。為了減少資源的使用,Token Manager被按需創(chuàng)建。為了創(chuàng)建一個單例的Token Manager對象,只是需要實現(xiàn)下面的typedef:

typedef ACE_Singleton Token_Mgr;
Token Manager單例將被用于本地和遠端的token死鎖檢測。在一個線程阻塞等待互斥量之前,它首先查詢Token Manager單例,來測試阻塞是否會導(dǎo)致死鎖狀態(tài)。對于系統(tǒng)中的每一個token,Token Manager單例維護一個持有token線程和所有阻塞等待在該token的線程記錄鏈表。這些數(shù)據(jù)將提供充足的檢測死鎖狀態(tài)的依據(jù)。使用Token Manager單例的過程如下:


// Acquire the mutex.
int Mutex_Token::acquire (void)
{
// If the token is already held, we must block.
if (mutex_in_use ()) {
// Use the Token_Mgr Singleton to check
// for a deadlock situation *before* blocking.
if (Token_Mgr::instance ()->testdeadlock ()) {
errno = EDEADLK;
return -1;
}
else
// Sleep waiting for the lock...
// Acquire lock...
}

變化

一種變化的Double Checked Locking模式實現(xiàn)可能是需要的,如果一個編譯器通過某種緩沖方式優(yōu)化了flag。在這種情況下,緩沖的粘著性(coherency)將變成問題,如果拷貝flag到多個線程的寄存器中,會產(chǎn)生不一致現(xiàn)象。如果一個線程更改flag的值將不能反映在其他線程的對應(yīng)拷貝中。

另一個相關(guān)的問題是編譯器移除了第二個flag==0檢測,因為它對于持有高度優(yōu)化特性的編譯器來說是多余的。例如,下面的代碼在激進的編譯器下將被跳過對flag的讀取,而是假定instance_還是為0,因為它沒有被聲明為volatile的。


Singleton *Singleton::instance (void)
{
if (Singleton::instance_ == 0)
{
// Only lock if instance_ isn't 0.
Guard guard (lock_);
// Dead code elimination may remove the next line.
// Perform the Double-Check.
if (Singleton::instance_ == 0)
// ...



解決這兩個問題的一個方法是生命flag為Singleton的volatile成員變量,如下:
private:
static volatile long Flag_; // Flag is volatile.
使用volatile將保證編譯器不會將flag緩沖到編譯器,同時也不會優(yōu)化掉第二次讀操作。使用volatile關(guān)鍵字的言下之意是所有對flag的訪問是通過內(nèi)存,而不是通過寄存器。

相關(guān)模式

Double Checked Locking模式是First-Time-In習慣用法的一個變化。First-Time-In習慣用法經(jīng)常使用在類似c這種缺少構(gòu)造器的程序語言中,下面的代碼展示了這個模式:


static const int STACK_SIZE = 1000;
static T *stack_;
static int top_;
void push (T *item)
{
// First-time-in flag
if (stack_ == 0) {
stack_ = malloc (STACK_SIZE * sizeof *stack);
assert (stack_ != 0);
top_ = 0;
}
stack_[top_++] = item;
// ...
}


第一次push被調(diào)用時,stack_是0,這將導(dǎo)致觸發(fā)malloc來初始化它自己。
posted on 2008-08-15 17:42 。。。。 閱讀(889) 評論(0)  編輯 收藏 引用 所屬分類: ACE
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲欧洲一区二区在线播放| 欧美aⅴ99久久黑人专区| 亚洲欧美成人一区二区在线电影| 久久aⅴ乱码一区二区三区| 久久在线免费| 国产精品永久| 亚洲国产精品成人综合| 欧美伊久线香蕉线新在线| 亚洲精品麻豆| 午夜精品在线看| 国产一区二区久久| 亚洲国内高清视频| 蜜桃av一区二区三区| 亚洲国产精品电影| 久久五月激情| 久久久7777| 国内精品久久久久影院薰衣草| 在线视频欧美精品| 日韩一区二区福利| 欧美午夜理伦三级在线观看| 日韩视频第一页| 欧美一区国产一区| 欧美亚洲视频在线看网址| 亚洲精品中文字幕在线| 欧美激情精品久久久久久| 亚洲区第一页| 亚洲精品日产精品乱码不卡| 欧美日韩日韩| 午夜精品亚洲| 久久爱www久久做| 一区二区三区日韩在线观看| 亚洲国内欧美| 99re6这里只有精品| 国产偷国产偷精品高清尤物| 蜜臀av一级做a爰片久久| 国产精品h在线观看| 欧美11—12娇小xxxx| 国产精品久久久久三级| 国产精品一区在线观看你懂的| 国产精品久久久久久久久久尿| 亚洲欧美日韩综合aⅴ视频| 校园春色综合网| 亚洲国产精品久久精品怡红院| 亚洲国产另类精品专区| 欧美日韩精品免费在线观看视频| 亚洲欧美另类国产| 久久手机精品视频| 国产精品99久久久久久www| 亚洲一区二区三区久久| 国产综合色一区二区三区 | 亚洲电影免费在线观看| 欧美激情一区二区三区在线视频 | 欧美一级视频| 久久久精品欧美丰满| 一本色道久久综合精品竹菊| 亚洲一区二区三区视频| 在线精品亚洲一区二区| 一本色道久久综合亚洲精品小说| 国内成人在线| 亚洲一品av免费观看| 亚洲大胆人体视频| 亚洲欧美另类国产| 一区二区三区产品免费精品久久75| 亚洲欧美在线aaa| 日韩午夜在线电影| 久久裸体视频| 亚洲欧美日韩区| 欧美成人精品在线| 亚洲视频 欧洲视频| 牛牛影视久久网| 国产精品美女www爽爽爽视频| 欧美大片网址| 国内精品伊人久久久久av影院| 日韩视频永久免费观看| 亚洲国产成人精品女人久久久 | 欧美成人精精品一区二区频| 欧美一区二区日韩| 欧美午夜视频网站| 亚洲国产精品成人va在线观看| 国产亚洲毛片| 亚洲在线免费视频| 亚洲欧美成aⅴ人在线观看| 欧美极品在线观看| 欧美高清hd18日本| 久久影院午夜片一区| 性做久久久久久久久| 欧美特黄视频| 99re6这里只有精品视频在线观看| 亚洲国产精品毛片| 久久夜色精品国产| 美女成人午夜| 亚洲第一页自拍| 久久亚洲图片| 亚洲电影网站| 亚洲精品日韩欧美| 蜜臀av性久久久久蜜臀aⅴ| 欧美国产亚洲精品久久久8v| 亚洲成人资源| 美女精品自拍一二三四| 欧美a级片网站| 在线观看91精品国产麻豆| 久久综合给合久久狠狠狠97色69| 久热爱精品视频线路一| 在线观看亚洲精品视频| 免费欧美视频| 日韩午夜在线观看视频| 在线午夜精品| 国产精品任我爽爆在线播放 | 国产免费亚洲高清| 欧美一区二区三区日韩| 久久综合久色欧美综合狠狠| 激情久久久久| 欧美大片免费久久精品三p| 亚洲黑丝在线| 亚洲欧美国产高清| 国产亚洲一区二区三区在线播放| 久久久久五月天| 亚洲欧洲在线观看| 亚洲欧美激情精品一区二区| 国产视频不卡| 欧美电影免费| 亚洲图片你懂的| 蜜乳av另类精品一区二区| 亚洲精品在线视频观看| 国产精品毛片a∨一区二区三区|国 | 欧美亚洲免费在线| 狠狠综合久久av一区二区老牛| 久久久久国产精品一区三寸 | 欧美日韩在线免费视频| 亚洲免费伊人电影在线观看av| 久久婷婷国产综合精品青草| 亚洲欧洲精品成人久久奇米网| 欧美午夜精品久久久久久孕妇 | 久久一综合视频| 99国产精品久久久久老师| 久久久综合视频| 宅男噜噜噜66一区二区| 国内精品久久久久久 | 久久爱另类一区二区小说| 亚洲激情第一区| 国产精品视频久久久| 久久久五月婷婷| 亚洲午夜精品国产| 亚洲精品一区中文| 亚洲精品久久久久久久久久久久 | 在线精品观看| 国产精品美女久久久免费| 久久免费一区| 亚洲性人人天天夜夜摸| 男人天堂欧美日韩| 午夜日韩在线观看| 亚洲精品国产精品国产自| 国产日韩欧美日韩| 欧美精品在线观看播放| 久久久www| 亚洲欧美在线免费| 99精品欧美一区| 欧美激情bt| 欧美风情在线观看| 久久精品免费播放| 欧美亚洲一区二区三区| 亚洲午夜在线视频| 99视频精品免费观看| 最近中文字幕日韩精品 | 一区二区av在线| 亚洲高清久久网| 好吊成人免视频| 国产一区二区高清视频| 国产噜噜噜噜噜久久久久久久久| 欧美日本精品一区二区三区| 久久综合九九| 久久久久88色偷偷免费| 久久精品国产一区二区三区免费看| 亚洲欧美精品在线观看| 亚洲女人天堂av| 亚洲欧美国产高清| 亚洲高清一区二| 亚洲午夜一区二区三区| 正在播放欧美一区| 亚洲乱码精品一二三四区日韩在线 | 国产欧美精品日韩区二区麻豆天美 | 欧美aⅴ一区二区三区视频| 久久免费视频这里只有精品| 久久久国产91| 麻豆精品在线视频| 欧美电影免费观看大全| 欧美乱在线观看| 欧美三级黄美女| 国产精品久久毛片a| 国产精品永久免费在线| 国产精品有限公司| 伊人久久亚洲热| 亚洲三级影片| 亚洲欧美在线视频观看| 久久激情婷婷| 亚洲第一伊人| 在线亚洲免费视频| 欧美影院午夜播放| 欧美成人精品在线播放| 欧美性片在线观看|