freepeople性欧美熟妇, 色戒完整版无删减158分钟hd, 无码精品国产vα在线观看DVD, 丰满少妇伦精品无码专区在线观看,艾栗栗与纹身男宾馆3p50分钟,国产AV片在线观看,黑人与美女高潮,18岁女RAPPERDISSSUBS,国产手机在机看影片

正文內容

03講_線程進程安全-文庫吧

2024-12-25 07:20 本頁面


【正文】 能保證程序的運行結果的正確性。在某些項目中,經常會出現(xiàn)線程同步的問題,即:多個線程在訪問同一資源時,會出現(xiàn)安全問題。本節(jié)基于一個簡單的案例,針對線程的同步問題進行闡述。 所謂同步,就是在發(fā)出一個功能調用時,在沒有得到結果之前,該調用就不返回,同時其它線程也不能調用這個方法。通俗地講,一個線程是否能夠搶占 CPU,必須考慮另一個線程中的某種條件,而不能隨便讓操作系統(tǒng)按照默認方式分配 CPU,如果條件不具備,就應該等待另一個線程運行,直到條件具備。 案例分析 給出一個案例:有若干張飛機票, 2個線程去賣它們,要求沒有票時能夠提示:沒有票了。以最后剩下 3張票為例。首先用傳統(tǒng)方法來編寫這段代碼。 代碼如 。 運行,控制臺打印如下: 這段程序貌似沒有問題。但是它是很不安全的,并且這種不安全性很難發(fā)現(xiàn),會給項目后期維護帶來巨大的代價。 觀察程序中的代碼行 1處的注釋,當只剩下一張票時,線程 1賣出了最后一張票,接著要運行 ticketNum,但在 ticketNum還沒來得及運行的時候,線程 2有可能搶占 CPU,來判斷當前有無票可賣,此時,由于線程 1還沒有將 ticketNum,當然票數(shù)還是 1,線程 2判斷還可以買票,這樣,最后一張票賣出了兩次。當然,上面的程序中,沒有給線程 2以買票的機會,實際上票都由線程 1賣出,我們看不出其中的問題。為了讓大家看清這個問題,我們模擬線程 1和線程 2交替賣票的情況。 將 : 該代碼中,增加了一行:程序休眠 1000毫秒,讓另一個線程來搶占 CPU。運行,控制臺打印如下: 最后一張票被賣出兩次,系統(tǒng)不可靠。 更為嚴重的是,該問題的出現(xiàn)很具有隨機性。比如,有些項目在實驗室運行階段沒有問題,因為哪個線程搶占 CPU,是由操作系統(tǒng)決定的,用戶并沒有權利干涉,也無法預測,所以,項目可能在商業(yè)運行階段出現(xiàn)了問題,等到維護人員去查問題的時候,由于問題出現(xiàn)的隨機性,問題可能就不出現(xiàn)了。這種工作往往給維護帶來了巨大的代價。 以上案例是多個線程消費有限資源的情況,該情況下還有很多其他案例,如:多個線程,向有限空間寫數(shù)據時: ?線程 1寫完數(shù)據,空間滿了,但沒來得及告訴系統(tǒng); ?此時另一個線程搶占 CPU,也來寫,不知道空間已滿,造成溢出。 解決方案 怎樣解決這個問題?很簡單,就是讓一個線程賣票時其他線程不能搶占 CPU。根據定義,實際上相當于要實現(xiàn)線程的同步,通俗地講,可以給共享資源(在本例中為票)加一把鎖,這把鎖只有一把鑰匙。哪個線程獲取了這把鑰匙,才有權利訪問該共享資源。 有一種比較直觀的方法,可以在共享資源(如“票”)每一個對象內部都增加一個新成員,標識“票”是否正在被賣中,其他線程訪問時,必須檢查這個標識,如果這個標識確定票正在被賣中,線程不能搶占 CPU。這種設計理論上當然也是可行,但由于線程同步的情況并不是很普遍,僅僅為了這種小概率事件,在所有對象內部都開辟另一個成員空間,帶來極大的空間浪費,增加了編程難度,所以,一般不采用這種方法。現(xiàn)代的編程語言的設計思路都是把同步標識加在代碼段上,確切的說,是把同步標識放在“ 訪問共享資源(如賣票)的代碼段”上。 不同語言中,同步代碼段的實現(xiàn)模型類似,只是表達方式有些不同。這里以 Java語言為例,在 Java語言中, synchronized關鍵字可以解決這個問題,整個語法形式表現(xiàn)為: 注意, synchronized后的“同步鎖對象”,必須是可以被各個線程共享的,如 this、某個全局標量等。不能是一個局部變量。 其原理為:當某一線程運行同步代碼段時,在“同步鎖對象”上置一標記,運行完這段代碼,標記消除。其他線程要想搶占 CPU運行這段代碼,必須在“同步鎖對象”上先檢查該標記,只有標記處于消除狀態(tài),才能搶占 CPU。在上面的例子中, this是一個“同步鎖對象”。 synchronized(同步鎖對象 ) { // 訪問共享資源,需要同步的代碼段 } 因此,在上面的案例中,可以將將賣票的代碼用synchronized代碼塊包圍起來,“同步鎖對象”取 this。 如代碼 。 運行,可以得到如下效果。 這說明程序運行完全正常。 從以上代碼可以看出,該方法的本質是將需要獨占 CPU的代碼用synchronized(this)包圍起來。如前所述,一個線程進入這段代碼之后,就在 this上加了一個標記,直到該線程將這段代碼運行完畢,才釋放這個標記。如果其他線程想要搶占 CPU,先要檢查 this上是否有這個標記。若有,就必須等待。 但是可以看出,該代碼實際上運行較慢,因為一個線程的運行,必須等待另一個線程將同步代碼段運行完畢。因此,從性能上講,線程同步是非常耗費資源的一種操作。我們要盡量控制線程同步的代碼段范圍,理論上說,同步的代碼段范圍越小,段數(shù)越少越好,因此在某些情況下,推薦將小的同步代碼段合并為大的同步代碼段。 實際上,在 Java內,還可以直接把 synchronized關鍵字直接加在函數(shù)的定義上,這也是一種可以推薦的方法。 不過,值得一提的是,如果不能確定整個函數(shù)都需要同步,那就要盡量避免直接把 synchronized加在函數(shù)定義上的做法。如前所述,要控制同步粒度,同步的代碼段越小越好,synchronized控制的范圍越小越好,否則造成不必要的系統(tǒng)開銷。所以,在實際開發(fā)的過程中,要十分小心,因為過多的線程等待可能造成系統(tǒng)性能
點擊復制文檔內容
教學課件相關推薦
文庫吧 www.dybbs8.com
備案圖鄂ICP備17016276號-1