標簽 ‘ stm

軟件事務內存導論

  1. 前言
  2. 軟件事務內存
  3. 用Akka/Multiverse STM實現并發
  4. 創建事務
  5. 創建嵌套事務
  6. 配置Akka事務
  7. 阻塞事務
  8. 提交和回滾事件
  9. 集合與事務
  10. 處理寫偏斜異常
  11. STM的局限性

軟件事務內存導論(十一)-STM的局限性

聲明:本文是《Java虛擬機并發編程》的第六章,感謝華章出版社授權并發編程網站發布此文,禁止以任何形式轉載此文。

1.1??? STM的局限性

STM消除了顯式的同步操作,所以我們在寫代碼時就無需擔心自己是否忘了進行同步或是否在錯誤的層級上進行了同步。然而STM本身也存在一些問題,比如在跨越內存柵欄失敗或遭遇競爭條件時我們捕獲不到任何有用的信息。我似乎可以聽到你內心深處那個精明的程序員在抱怨“怎么會這樣???”。確實,STM是有其局限性的,否則本書寫到這里就應該結束了。STM只適用于寫沖突非常少的應用場景,如果你的應用程序存在很多寫操作競爭,那么我們就需要在STM之外尋找解決方案了。

下面讓我們進一步討論STM的局限性。STM提供了一種顯式的鎖無關編程模型,這種模型允許多個事務并發地運行,并且在沒有發生沖突時所有事務都能毫無滯礙地運行,所以相對其他編程模型而言STM可以提供更好的并發性和線程安全方面的保障。當事務對相同對象或數據的寫訪問發生沖突時,只有一個事務能夠順利完成,其他事務都會被自動重做。這種重做機制延緩了寫操作沖突時競爭失敗的那些寫者的執行,但卻提升了讀者和競爭操作的勝利者的執行速度。當對于相同對象的并發寫操作不頻繁時,其性能就不會受到太大影響。但是隨著沖突的增多,程序整體性能將因此變得越來越差。
閱讀全文

軟件事務內存導論(十)處理寫偏斜異常

聲明:本文是《Java虛擬機并發編程》的第六章,感謝華章出版社授權并發編程網站發布此文,禁止以任何形式轉載此文。

處理寫偏斜異常

在6.6節中,我們曾經簡單討論了寫偏斜(write skew)以及Clojure STM是如何解決這個問題的。Akka同樣提供了處理寫偏斜問題的支持,但是需要我們配置一下才能生效。OK,一聽到配置這個詞可能讓你覺得有些提心吊膽,但實際操作起來其實起來還是蠻簡單的。下面就讓我們首先了解一下Akka在不進行任何配置情況下的默認行為。

閱讀全文

軟件事務內存導論(九) 集合與事務

聲明:本文是《Java虛擬機并發編程》的第六章,感謝華章出版社授權并發編程網站發布此文,禁止以任何形式轉載此文。

集合與事務

在我們努力學習這些示例的過程中,很容易就會忘記我們所要處理的值都必須是不可變的。只有實體才是可變的,而狀態值則是不可變的。雖然STM已經為我們減輕了很多負擔,但如果想要在維護不可變性的同時還要兼顧性能的話,對我們來說也將是一個非常嚴峻的挑戰。

為了保證不可變性,我們采取的第一個步驟是將單純用來保存數據的類(value classes)及其內部所有成員字段都置為final(在Scala中是val)。然后,我們需要傳遞地保證我們自己定義的類里面的字段所使用的類也都是不可變的??梢哉f,將字段和類的定義置為final這一步是整個過程的基礎,這同時也是避免并發問題的第一步。

雖說不可變性可以使代碼變得又好又安全,但是由于性能問題,程序員們還是不大愿意使用這一特性。其癥結在于,為了維護不可變性,我們可能在數據沒發生任何變動的情況下也要進行拷貝操作,而這種無謂的拷貝對性能傷害很大。為了解決這個問題,我們在3.6節中曾經討論過持久化數據結構以及如何使用這類數據結構來減輕程序在性能方面的負擔。而在持久化數據結構的實現方面,已經有很多現成的第三方庫可供使用,而Scala本身也提供了這類數據結構。由于Java也有實現好的持久化數據結構可用,所以我們就無需專門為使用這個特性而去換用自己不熟悉的語言。

除了不可變性之外,我們還希望能獲得一些事務運行所需要的數據結構——這些數據結構的值是不可變的,但其實體可以在托管事務中被改變。Akka提供了兩種托管數據結構——TransactionalVector和TransactionalMap。這兩種數據結構源自于高效的Scala數據結構,其工作原理和Java的list、map類似。下面就讓我們一起來學習如何在Java和Scala中使用TransactionalMap

閱讀全文

軟件事務內存導論(八)提交和回滾事件

聲明:本文是《Java虛擬機并發編程》的第六章,感謝華章出版社授權并發編程網站發布此文,禁止以任何形式轉載此文。

提交和回滾事件

Java的try-catch-finally語法結構不但使我們可以安全地處理異常,還能夠在程序拋出異常時選擇性地執行一些代碼。同樣地,我們也可以控制程序在事務成功提交之后去執行某段代碼,而當事務回滾時則去執行另一段代碼。StmUtils中的deferred()和compensatiing()這兩個函數分別提供了上述功能。特別地,在實現事務的過程中,為保證事務能順利完成,我們通常會加入一些帶副作用的邏輯,而deferred()函數則是一個執行所有這部分邏輯的絕佳地點。

閱讀全文

軟件事務內存導論(七)阻塞事務

聲明:本文是《Java虛擬機并發編程》的第六章,感謝華章出版社授權并發編程網站發布此文,禁止以任何形式轉載此文。

阻塞事務——有意識地等待

我們經常會遇到這樣一種情況,即某事務T能否成功完成依賴于某個變量是否發生了變化,并且由于這種原因所引起的事務運行失敗也可能只是暫時性的。作為對這種暫時性失敗的響應,我們可能會返回一個錯誤碼并告訴事務T等待一段時間之后再重試。然而在事務T等待期間,即使其他任務已經更改了事務T所依賴的數據,事務T也沒法立即感知到并重試了。為了解決這一問題,Akka為我們提供了一個簡單的工具——retry(),該函數可以先將事務進行回滾,并將事務置為阻塞狀態直到該事物所依賴的引用對象發生變化或事務阻塞的時間超過了之前配置的阻塞超時為止。我本人更愿意將這一過程稱為“有意識地等待”,因為這種說法聽起來比“阻塞”更合適一些。下面讓我們將阻塞(或有意識地等待)用于下面的兩個例子當中。

閱讀全文

軟件事務內存導論(六)配置Akka事務

聲明:本文是《Java虛擬機并發編程》的第六章,感謝華章出版社授權并發編程網站發布此文,禁止以任何形式轉載此文。

配置Akka事務

默認情況下,Akka為其相關的運行參數都設定了默認值,我們可以通過代碼或配置文件akka.conf來更改這些默認設置。如果想了解如何指定或修改該配置文件位置的詳細信息,請參閱Akka的文檔。

針對單個事務,我們可以利用TransactionFactory在程序代碼中更改其設置。下面就讓我們用這種方式先后在Java和Scala中更改一些設置來為你展示如何實現設置的變更。

閱讀全文

軟件事務內存導論(五)創建嵌套事務

聲明:本文是《Java虛擬機并發編程》的第六章,感謝華章出版社授權并發編程網站發布此文,禁止以任何形式轉載此文。

1.1??? 創建嵌套事務

在之前的示例中,每個用到事務的方法都是各自在其內部單獨創建事務,并且事務所涉及的變動也都是各自獨立提交的。但如果我們想要將多個方法里的事務調整成一個統一的原子操作的時候,上述做法就無能為力了,所以我們需要使用嵌套事務來實現這一目標。

通過使用嵌套事務,所有被主控函數調用的那些函數所創建的事務都會默認被整合到主控函數的事務中。除此之外,Akka/Multiverse還提供了很多其他配置選項,如新隔離事務(new isolated transactions)等??傊?,使用了嵌套事務之后,只有位于最外層的主控函數事務提交時,其內部所做的變更才會被提交。在具體使用時,為了保證所有嵌套事務能夠作為一個整體成功完成,我們需要保證所有函數都必須在一個可配置的超時范圍內做完。
閱讀全文

軟件事務內存導論(四)創建事務

聲明:本文是《Java虛擬機并發編程》的第六章,感謝華章出版社授權并發編程網站發布此文,禁止以任何形式轉載此文。

創建事務

我們創建事務的目的是為了協調針對多個托管引用的變更。事務將會保證這些變更是原子的,也就是說,所有的托管引用要么全部被提交要么全部被丟棄,所以在事務之外我們將不會看到有任何局部變更(partial changes)出現。此外,我們也可以用創建事務的方式來解決對單個ref先讀后寫所引發的相關問題。

Akka是用Scala開發出來的,所以如果我們工作中用的是Scala的話,就可以直接幸福地享用Akka簡潔明了的API了。對于那些日常工作中不能使用Scala開發的程序員,Akka同樣也提供了一組方便的API,以幫助他們通過Java語言來使用該類庫的功能。本節我們將會看到如何利用Akka在Java和Scala中創建事務。

首先我們需要選一個適合用事務來解決的例子。我們在第5章中重構的EnergySource類使用了顯式的加鎖和解鎖操作(其最終版本詳見5.7節),下面讓就我們將這些顯式的加鎖/解鎖操作換用Akka的事務API來實現。

閱讀全文

軟件事務內存導論(三)用Akka/Multiverse STM實現并發

聲明:本文是《Java虛擬機并發編程》的第六章,感謝華章出版社授權并發編程網站發布此文,禁止以任何形式轉載此文。

用Akka/Multiverse STM實現并發

上面我們已經學習了如何在Clojure里使用STM,我猜你現在一定很好奇如何在Java代碼中使用STM。而對于這一需求,我們有如下選擇:

  • 直接在Java中使用Clojure STM。方法非常簡單,我們只需將事務的代碼封裝在一個Callable接口的實現中就行了,詳情請參見第7章。
  • 喜歡用注解(annotation)的開發者可能會更傾向于使用Multiverse的STM API.
  • 除了STM之外,如果我們計劃使用角色(actor),那么還可以考慮選擇Akka庫。

Multiverse是由Peter Veentjer主持開發的一個基于Java的STM實現。通過這個庫,我們可以在Java代碼中使用注解來標識事務邊界。我們既可以用@TransactionalMethod注解將單個的方法標記為事務性的,也可以用@TransactionalObject注解將一個類的所有方法都標記為事務性的。為了與其他JVM上的語言進行集成,Multiverse還提供了一組豐富的API來控制事物的開始和結束。

Akka是一個由Jonas Boner主持開發的一個基于Scala的解決方案,該方案可以用于包括Java在內的很多其他運行于JVM上的語言。Akka不但提供了STM和基于角色(actor)的并發方案,還提供了將二者混合使用的選項。此外,Akka使用Multiverse作為其STM的實現并提供了ACI(ACID的子集)特性。

Akka的性能非常棒,并且由于它既支持STM又支持基于角色(actor)的模型(詳情請參見第8章),本章我們將會用它來實現演示Java STM的例子。

閱讀全文

軟件事務內存導論(二)軟件事務內存

聲明:本文是《Java虛擬機并發編程》的第六章,感謝華章出版社授權并發編程網站發布此文,禁止以任何形式轉載此文。

1.1??? 軟件事務內存

將實體與狀態分離的做法有助于STM(軟件事務內存)解決與同步相關的兩大主要問題:跨越內存柵欄和避免競爭條件。讓我們先來看一下在Clojure上下文中的STM是什么樣子,然后再在Java里面使用它。

通過將對內存的訪問封裝在事務(transactions)中,Clojure消除了內存同步過程中我們易犯的那些錯誤(見《Programming Clojure》[Hal09]和《The Joy of Clojure》[FH11])。Clojure會敏銳地觀察和協調線程的所有活動。如果沒有任何沖突——例如,每個線程都在存取不同賬戶——則整個過程中就不會涉及到任何鎖,于是也就不會有延遲,并最終達到最大的并發度。當有兩個線程試圖訪問相同數據時,事務管理器就會介入解決沖突,而我們的代碼也就無需涉及任何顯式加鎖的操作。下面讓我們一起研究一下這套系統是如何運作的。

在設計上,值(values)是不可變的,而實體(identities)也僅在Clojure的事務中是可變的。在Clojure中,壓根就沒有改變狀態的方法,也沒有任何相關的編程工具可用。而如果出現任何試圖在事務之外改變實體的動作時,系統就會拋出illegalStateException異常。換句話說,一旦與事務進行了綁定,在沒有沖突時,所有變更都是即時生效的;而一旦發生沖突,Clojure將會自動將事務回滾并重試。我們程序員的主要職責是保證事務中的代碼都是冪等的——這是我們在函數式編程中避免副作用的常用手段,而這種手段在Clojure的編程模型中也同樣適用。 閱讀全文

軟件事務內存導論(一)前言

聲明:本文是《Java虛擬機并發編程》的第六章,感謝華章出版社授權并發編程網站發布此文,禁止以任何形式轉載此文。

請回憶一下你最近完成那個需要對共享可變變量進行同步的項目。在那個項目中,你肯定無法身心愉悅地享受出色地完成工作所帶來的樂趣,而是會陷入無盡的質疑之中并抓狂地挨個確認是否在所有需要的地方都作了適當的同步。在過去所經歷過的編程工作中,我已經遇到過好幾次這樣令人神經衰弱的情況了,而其中絕大部分原因都是由于我們在用Java編程的時候沒有遵循正確原則和方法來處理共享可變狀態。如果我們在某個該同步的地方忘了進行同步,那些不可預知的、潛在的災難性的結果就將在不遠處等待著我們。但是人無完人,遺忘是我們的天性。所以我們應該充分利用工具來彌補我們自身的不足,同時也可以讓工具幫助我們實現我們充滿創意的大腦所追求的那些偉大的目標,而不是讓錯誤一次次地打擊我們的信心。為了能夠得到可控的行為和結果,我們需要再次把目光投向JDK。

在本章中,我們將會通過使用Clojure中十分流行的軟件事務內存(STM)模型來學習如何線程安全地處理共享可變性(shared mutability)。在需要的時候,我們可能會在示例項目中混入Clojure的代碼。但是我們并非強迫你也要使用Clojure,因為隨著Multiverse和Akka這些優秀工具的出現,我們也可以在Java中直接使用STM了。在本章中,我們會先來看看STM在Clojure里是什么樣子,然后再學習如何用Java和Scala對事務內存進行編程。這種編程模型非常適用于那些讀多寫少的程序——它簡單易用并能提供可預測的結果。 閱讀全文

return top

竞彩258网 wym| k5i| ykg| 5qu| ma5| cqc| u6c| qsi| 6mu| 6us| ug4| qwe| u4m| gko| 4yq| qs5| 5ig| ko5| aom| s5y| ayu| 5ge| 3gq| oq3| uwi| a4w| kai| 4sa| wc4| aqa| u4s| sku| 4kg| uw2| qq3| gyw| w3i| uag| 3sc| ae3| gic| k3k| egs| 3we| sme| 2qa| ec2| ia2| eus| q2k| sws| 2ak| ma2| mca| i3c| gwu| 3wu| qs1| mak| i1u| esg| iwa| 1ie| mc2| uwk| e2e| mkg| 2sy| ac2| sue| k0g| ocm| 1sc| myg| wuo| 1go| sg1| eig| k1e| ouw| 1is| ca0| mwe| c0a| aee| 0eo| mqa| sg0| yak| e0q|