成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

旺財(cái)和小強(qiáng)的三生三世

企業(yè)動態(tài)
旺財(cái)和小強(qiáng)是線程池的兩個(gè)線程, 他們經(jīng)常做的工作就是對一個(gè)數(shù)加加減減,用人類的話來說就是存款,取款。

 ***世

旺財(cái)和小強(qiáng)是線程池的兩個(gè)線程, 他們經(jīng)常做的工作就是對一個(gè)數(shù)加加減減,用人類的話來說就是存款,取款。

  1. public class Account{ 
  2.    private int balance; 
  3.    public synchronized void deposit(int amt){ 
  4.        balance += amt; 
  5.    } 
  6.  
  7.    public synchronized void withdraw(int amt){ 
  8.        if(balance >= amt){ 
  9.            balance -= amt; 
  10.        } 
  11.        throw new RuntimeException("insufficent blance"); 
  12.    } 

(友情提示,可左右滑動,下同)

每次進(jìn)行存款,取款操作的時(shí)候,他們兩個(gè)都需要獲得一把鎖,這樣就能保證同一時(shí)刻只有一個(gè)人在修改,不會出亂子。

這一天,他們倆又遇到了一個(gè)叫做轉(zhuǎn)賬的操作:

  1. public void transfer(Account from,Account toint amt){ 
  2.    synchronized(from){ 
  3.        synchronized(to){ 
  4.            from.withdraw(amt); 
  5.            to.deposit(amt); 
  6.        } 
  7.    } 

旺財(cái)說:“這個(gè)程序員不錯(cuò),考慮得挺周全。轉(zhuǎn)賬的時(shí)候把兩個(gè)賬戶都鎖住了,安全!”

小強(qiáng)說:“沒錯(cuò),執(zhí)行吧。”

旺財(cái)這個(gè)線程從A向B轉(zhuǎn)賬 , 與此同時(shí),小強(qiáng)從B向A轉(zhuǎn)賬

令旺財(cái)和小強(qiáng)沒有想到的是,居然出現(xiàn)了死鎖。

 

類似的事件發(fā)生不少, 線程池的線程用光了,Tomcat被迫重啟,這個(gè)世界毀滅了。

第二世

新生代的旺財(cái)和小強(qiáng)從線程池中出來, Tomcat老大給他們講了上一代旺財(cái)和小強(qiáng)的故事, 對他們諄諄教導(dǎo):“做轉(zhuǎn)賬操作的時(shí)候一定要小心,別死鎖了!”

旺財(cái)和小強(qiáng)有點(diǎn)兒憤憤不平:“這我們倆也控制不了啊,這要看程序員寫的代碼,以及操作系統(tǒng)中的線程調(diào)度啊!”

不滿歸不滿,他倆還是有點(diǎn)小期待,想看看可怕的轉(zhuǎn)賬代碼到底怎么樣。

沒過多久, 他倆就如愿了:

  1. public static final Object lock = new Object(); 
  2. public void transfer(Account from,Account toint amt){ 
  3.    int fromHash = System.identityHashCode(from); 
  4.    int toHash = System.identityHashCode(to); 
  5.    if(fromHash > toHash){ 
  6.        synchronized(from){ 
  7.            synchronized(to){ 
  8.                from.withdraw(amt); 
  9.                to.deposit(amt); 
  10.            } 
  11.        } 
  12.    } 
  13.    else if(toHash > fromHash){ 
  14.        synchronized(to){ 
  15.            synchronized(from){ 
  16.                from.withdraw(amt); 
  17.                to.deposit(amt); 
  18.            } 
  19.        } 
  20.    } 
  21.    else { 
  22.        synchronized(lock){ 
  23.            synchronized(from){ 
  24.                synchronized(to){ 
  25.                    from.withdraw(amt); 
  26.                    to.deposit(amt); 
  27.                } 
  28.            } 
  29.        } 
  30.    } 

看到這樣的代碼, 旺財(cái)?shù)刮艘豢跉?,撓著頭說:“搞什么鬼,轉(zhuǎn)個(gè)賬都這么麻煩!”

小強(qiáng)說:“老大不是說了嗎,上一代線程老是在轉(zhuǎn)賬這里出錯(cuò),于是代碼就重寫了。你看,這一次寫得就很嚴(yán)謹(jǐn)了,每一次都會去比較兩個(gè)賬戶的大小(通過hash code),誰大就先獲得誰的鎖。 ”

旺財(cái)說:“奧,相當(dāng)于把賬戶給排了序,假設(shè)賬戶A大于賬戶B , 那我們倆轉(zhuǎn)賬的時(shí)候,每次都先獲得A的鎖,這樣就不會互相等待了。 ”

 

“沒錯(cuò),還有一個(gè)特殊情況,如果這兩個(gè)賬戶的hash code 相同,那就再去競爭另外一個(gè)特殊的鎖,誰搶到誰就可以先執(zhí)行。另一個(gè)就在那里等待。”

旺財(cái)和小強(qiáng)這次順利地把轉(zhuǎn)賬給執(zhí)行完了,回去給Tomcat匯報(bào)了一遍。

Tomcat老大感慨地說:“有這么復(fù)雜的代碼,可見使用‘共享內(nèi)存’的方式來并發(fā)編程很不容易啊!”

“共享內(nèi)存?”

“對啊,你看這些賬戶的數(shù)據(jù),每個(gè)線程都可以訪問,不就是共享內(nèi)存嗎, 為了能夠安全訪問,只有來‘加鎖’了。 古人說,這個(gè)世界上有兩種構(gòu)建軟件的方式,一種方法是使其足夠簡單以至于不存在明顯的缺陷,另外一種是使其足夠復(fù)雜以至于看不出有什么問題。我很擔(dān)心啊, 現(xiàn)在這個(gè)系統(tǒng)就屬于第二種,不知道有多少坑在等著我們呢!”

(碼農(nóng)翻身: 實(shí)際上這句話是托尼·霍爾說的)

老大不幸言中,終于有一天,這個(gè)復(fù)雜到看不出問題的系統(tǒng)崩潰了,這個(gè)世界又毀滅了。

第三世

第三代的旺財(cái)和小強(qiáng)從線程池出來。

出發(fā)前,Tomcat老大把前兩代線程遇到的問題給他們說了一遍,威脅說:如果再出現(xiàn)死鎖,小心你們兩個(gè)的腦袋!

旺財(cái)和小強(qiáng)戰(zhàn)戰(zhàn)兢兢,如履薄冰地執(zhí)行代碼。

最終他們還是遇到了傳說中的可怕的轉(zhuǎn)賬代碼:

  1. def transfer(from: Account, to: Account,amt:Int){ 
  2.    atomic{ 
  3.        from.withdraw(amt); 
  4.        to.deposit(amt); 
  5.    } 

旺財(cái)非常吃驚:“這是什么代碼?不是Java?”

小強(qiáng)說:“嗯,不是Java ,是Scala寫的,這是運(yùn)行在JVM上的一個(gè)語言。”

(碼農(nóng)翻身注:實(shí)際上JVM線程能看到的只是Java 字節(jié)碼,根本看不到源碼,也就不知道是Java寫的代碼,還是Scala寫的代碼, 這里只是為了展示方便。)

旺財(cái)說:“怎么這么簡單,會不會出問題?那個(gè)atomic是怎么回事?表示原子執(zhí)行?”

小強(qiáng)也有點(diǎn)懵,不敢貿(mào)然去執(zhí)行:“咱們還是去問Tomcat老大吧。”

Tomcat看了一眼:“人類程序員又改代碼了啊,開始使用Software Transaction Memory(STM)了。 去把STM老頭兒叫來,讓他給你倆解釋。”

STM老頭兒滿臉滄桑:“放心執(zhí)行吧,只要你把代碼放到atomic中,我就能保證他們像事務(wù)一樣,實(shí)現(xiàn)ACID,哦不,D(持久化)實(shí)現(xiàn)不了,這些數(shù)據(jù)都是在內(nèi)存中的。”

“這有什么用? ”

“可以讓你們倆安全地并發(fā)執(zhí)行啊?”

旺財(cái)和小強(qiáng)面面相覷,這連鎖都沒有,還安全地并發(fā)?

“別看沒有鎖,” STM老頭兒說,“在atomic代碼開始執(zhí)行的時(shí)候,我會記錄下代碼塊涉及到的數(shù)據(jù)的值(復(fù)制了一份),然后才真正執(zhí)行,執(zhí)行完了要‘提交’, 這時(shí)候我會看看那些數(shù)據(jù)的值是否也被別的線程改動了,如果有改動,那本次改動就撤銷,重新從代碼開始處執(zhí)行。 ”

老頭兒畫了一個(gè)圖,展示旺財(cái)從賬戶A給賬戶B轉(zhuǎn)20元, 與此同時(shí)小強(qiáng)從B向A轉(zhuǎn)30元。

 

還真是,沒有加鎖就安全地完成了兩個(gè)并發(fā)操作。

當(dāng)然,老頭兒為了實(shí)現(xiàn)這個(gè)atomic操作,背后偷偷做了不少事情:復(fù)制數(shù)據(jù),提交,重復(fù)執(zhí)行。

旺財(cái)想起來自己曾經(jīng)執(zhí)行過一下Java 的Compare and swap的代碼,說道:“你這不就是CAS嘛!”

老頭兒說:“原理上類似,都是樂觀鎖,不過我這個(gè)方式和數(shù)據(jù)庫的事務(wù)更加類似,所以叫做Software Transaction Memory。”

小強(qiáng)想了想,說道:“不對啊,atomic是個(gè)代碼塊,里邊可能有很多代碼,涉及到很多class, 你怎么知道哪些字段需要被STM管理起來啊!”

STM老頭兒說:“這真是個(gè)好問題,實(shí)際上,需要程序員們來告訴我。比如使用這個(gè)方法”

  1. class Account(val initialBalance : Int){ 
  2.  val balance = Ref(initialBalance) 
  3.  ...... 

“看到那個(gè)Ref沒有,這就是一種辦法,通過它,我就知道這個(gè)balance的字段需要讓我管理起來,在atomic代碼塊運(yùn)行的時(shí)候,就需要復(fù)制它的值,比較它的值。”

“明白了,但是‘重復(fù)執(zhí)行’有問題啊,假設(shè)程序員張大胖是這么寫代碼的:”

  1. def transfer(from: Account, to: Account,amt:Int){ 
  2.     atomic{ 
  3.         from.withdraw(amt); 
  4.         ...在這里執(zhí)行一些其他操作,例如打印日志,發(fā)送郵件..... 
  5.         to.deposit(amt); 
  6.     } 

“這其中有一些打印日志,發(fā)送郵件的操作,那你重復(fù)執(zhí)行,豈不會執(zhí)行很多次,就完全亂套了。”

STM老頭兒說:“不錯(cuò),想得挺深,你說的這些操作,我把他們叫做副作用,不能重復(fù)執(zhí)行,不能放到atomic代碼塊中讓STM管理。換句話說atomic中的代碼應(yīng)該是冪等的。如果違背了這一點(diǎn),后果自負(fù)!”

小強(qiáng)心中一凜:“這是程序員要操心的事情了,不管我倆的事情, 不過即使如此,他們的代碼也極度地簡化了,只需要用個(gè)atomic,就能實(shí)現(xiàn)安全地并發(fā),實(shí)在是太爽了。”

旺財(cái)說道:“你說得天花亂墜,這STM有什么缺點(diǎn)?”

老頭兒說:“天下沒有免費(fèi)的午餐,很容易想到STM的局限性, 如果對于同一個(gè)數(shù)據(jù),并發(fā)寫入很多的時(shí)候,沖突就大大增加了,不斷地重復(fù)執(zhí)行,效率很低。所以更適合寫入少,讀取多的場景。”

“好吧,我們這就執(zhí)行這個(gè)轉(zhuǎn)賬操作,有問題就找你!”

【本文為51CTO專欄作者“劉欣”的原創(chuàng)稿件,轉(zhuǎn)載請通過作者微信公眾號coderising獲取授權(quán)】

 

戳這里,看該作者更多好文

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2021-11-23 23:13:11

數(shù)據(jù)庫安全工具

2019-02-12 09:45:27

2018-06-14 10:20:20

2009-06-18 16:54:11

Fedora 11910

2010-09-17 10:45:04

李彥宏

2019-06-27 17:30:46

貝銳科技網(wǎng)絡(luò)傳輸

2022-06-02 07:36:14

5G5G商用

2017-10-11 09:04:16

服務(wù)器劫難死機(jī)

2015-06-02 16:16:56

GoogleAndroid M

2016-08-02 11:03:22

數(shù)字 系列

2016-09-13 15:24:24

孟憲坤 思維

2018-06-05 15:41:22

進(jìn)程線程協(xié)程

2010-08-20 09:02:57

菲律賓總統(tǒng)互聯(lián)網(wǎng)

2020-11-16 17:50:21

華為北京聯(lián)通5G

2013-07-24 10:24:55

蘋果iPhone財(cái)報(bào)

2014-01-17 17:20:18

昆騰數(shù)據(jù)保護(hù)大數(shù)據(jù)管理

2014-05-04 14:15:31

2022-04-26 15:17:52

AI數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 97久久久久久 | 日韩av在线一区 | 亚洲精品一二区 | 欧美日韩在线观看一区 | 久久综合久色欧美综合狠狠 | 久久久久久亚洲精品不卡 | 99re视频在线观看 | 亚洲精品久久久久久久久久久 | 国产高清视频在线观看 | 欧美日韩视频 | 欧美日韩综合视频 | 欧美不卡在线 | 羞羞视频一区二区 | 成人深夜福利 | 中国黄色毛片视频 | 色综合色综合网色综合 | 色噜噜狠狠色综合中国 | 亚洲色欲色欲www | 91精品国产高清久久久久久久久 | 久久免费看 | 久久精品一区二区视频 | 久久精品国产一区二区三区 | 亚洲激情综合网 | 欧美理论| 在线一区二区观看 | 亚洲欧美国产精品一区二区 | 91社区视频 | 91精品久久久久久久久中文字幕 | 国产美女一区 | 成年人黄色小视频 | 亚洲91 | 亚洲精品在线免费播放 | 毛片99 | 亚洲成人三级 | 在线免费观看a级片 | 久久国产精品视频 | 日本一区二区三区在线观看 | 亚洲国产欧美91 | 国产乱码精品一区二区三区中文 | www国产成人免费观看视频,深夜成人网 | 在线午夜 |