巧用Dictionary物件實現執行緒安全類 例項

2021-04-22 17:47:20 字數 3110 閱讀 3416

在前一面篇文章[

設計安全的多執行緒應用程式(執行緒安全)

]中,我們講了,什麼是執行緒安全,列舉一些常見的執行緒安全和非執行緒安全的情況。還沒對執行緒安全了解的同學請點上面的鏈結。現在我們來看執行緒不安全的本質是什麼。

我們來想想在單執行緒的情況下安全,為什麼在多執行緒的情況下是不安全的呢?無非就是因為多執行緒是並行執行,當然並行執行本身是沒有錯的。如果這些並行跑起來的執行緒,出現下列情況時可能會導致執行緒不安全。第一,爭搶獨佔的資源如同時寫乙個檔案,對獨佔的資源的排它鎖。第二,程式中的全域性物件,如類中對靜態成員,被多個執行緒同時更新(修改或者刪除),會產生髒的資料或者是其它執行緒得不到正確的資料的後果;同乙個類例項的非靜態成員,被此例項中的函式使用(其中有修改例項成員的功能),此時兩個以上執行緒同時使用時,就可能使類成員的狀態對同乙個執行緒的使用的不一致性。

由此,可以看出,執行緒安全的本質就是,要保護全域性物件,在使用時只能被乙個執行緒使用(包括讀,寫,刪除)(注意,對全域性物件只限於唯讀,那麼是執行緒安全的)。解決的方法無非就是兩種,第一,把這個物件或者資源鎖住,即等我用完了,其它執行緒才能再能,否則其它執行緒等待,這也是最常見的方式。第二,給每個執行緒分配屬於只屬於自己的"全域性物件"(這樣聽起來好像有點彆扭)。

要注意的一點是,很多語句的類庫中的類,都沒在實現執行緒安全,這是因為基於效能的考慮,這樣的情況下,就讓我們程式設計師自己來決定實現執行緒安全。

下面這兩種設計執行緒安全類的例子:

第一,用lock語句(在c#中)

1,鎖住同乙個例項中的全域性資源(同一例項中非靜態成員)

public

void

function()}

2,鎖住類中靜態成員

static

stringbuilder cstrbuild 

=new

stringbuilder();

static

system.object lockthis 

=new

system.object();

public

void

function()}

第二,使用給每乙個執行緒分配自己的「全域性物件」的方法,實現乙個帶有快取的寫檔案功能的執行緒安全的類(避免每條資料寫一次,造成io瓶頸)。

它的原則是給每個執行緒分配自己的「全域性物件」。

實現功能:

當每個執行緒的stringbuilder物件,到達一定長度 const

intcbufferlenght 

=10000*38

;  後才寫入檔案。 

步驟是:

1, 宣告乙個分局物件集合,我用了dictionary物件,key是執行緒id,value就是它的「全域性物件」

static

dictionary

<

int, stringbuilder

>

clbufferofethread 

=new

dictionary

<

int, stringbuilder

>

();

2,需要注意的是,當第一次將資料加入到全域性集合物件dictionary

時,需要鎖定

dictionary物件

lock

(lockbuffer)

3, 給dictionary物件賦值時,無需使用lock(因為它是執行緒獨佔的全域性物件,不會衝突,我給每個執行緒id分配了自己的「全域性物件」,即集合中的某個元素)

4,在虛構函式處理還未寫入檔案的資料

~streamwritewithbuffer()

valus.remove(

0, valus.length);}}

} 下面就是具體的**,

呼叫**:

streamwritewithbuffer streamwritewithbuffer 

=new

streamwritewithbuffer();

//////

writing

content

once a content was created

///

///limpid file name

///public

void

writelimpidlog(

string

pstrcontent)

catch

(exception ex)}

類實現:

using

system;

using

system.collections.generic;

using

system.text;

using

system.io;

using

system.threading;

namespace

project.common

public

streamwritewithbuffer()

~streamwritewithbuffer()

valus.remove(

0, valus.length);}}

}private

static

object lockwrite 

=new

object();

private static object lockbuffer = new object();

public

void

writeline(

string

plimpidfilename, 

string

pstrcontent)

else

}clbufferofethread[thread.currentthread.managedthreadid].remove(

0, clbufferofethread[thread.currentthread.managedthreadid].length);}}

else}}

catch

(exception ex)

}public

void

dispose()}}

總之,執行緒安全除了在設計時要盡量避免以上的情況之外,還要反覆的測試你的類,或者程式,才能更終實現執行緒安全類。

Redis中字典 Dictionary 的實現

字典 字典,又稱為符號表 symbol table 關聯表 associative array 或對映 map 是一種用於儲存鍵值對 key value pair 的抽象資料結構。在字典裡面,乙個鍵 key 可以和乙個值 value 進行關聯 將鍵對映為值 字典中的每個鍵都是獨一無二的,程式可以在字...

VBA中Dictionary物件使用小結

自 vba中dictionary物件使用小結 dim dict 建立dictionary set dict createobject scripting.dictionary 增加專案 dict.add a 300 dict.add b 400 dict.add c 500 統計專案數 n dict...

在QTP中使用Dictionary物件

vbscript的dictionary 物件與perl的關聯陣列 associative array 類似,其中儲存的內容可以是任何資料,每乙個儲存的資料都與乙個唯一的鍵 key 關聯,鍵用於獲取每一項資料,鍵通常是整型或字串型別。在qtp中,可以把dictionary 當成陣列來用,而且可以隨時新...