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

如何把握編程世界的那把鎖

開發 開發工具
我們這里是個典型的弱肉強食的世界, 人口多而資源少,為了爭搶有限的資源,大家都在自己能運行的CPU時間片里拼了老命,經常為了一個變量的修改而打的頭破血流。

1.共享變量惹得禍

我們這里是個典型的弱肉強食的世界, 人口多而資源少,為了爭搶有限的資源,大家都在自己能運行的CPU時間片里拼了老命,經常為了一個變量的修改而打的頭破血流。

[[190760]]

100納秒以前, 我有幸占據了CPU,從內存中讀取了一個變量x == 100, 我把它加了1, 休息了一會兒后我打算把它寫回內存, 但是驚奇的發現: 內存中的x 已經變成102了。

估計是哪個不著調的線程在我休息的時候也讀取并且修改了x, 有不少好心的線程在沖我喊:不要寫回了! 但是寫回內存是我的指令啊, 你不讓我執行,難道讓我退出? 我只能毫不客氣的把101寫入內存, 把那個不符合我邏輯的值102給覆蓋掉, 這樣我才能執行下一條指令。

你看,單線程的邏輯正確并不表示多線程并發運行時的邏輯也能正確。

這樣的事情發生的多了,程序總是無法正確運行, 引起了人類的強烈不滿,小道消息說他們在考慮kill掉我們, 換編程語言了。

但是換編程語言有什么用,只要有共享變量,多線程讀寫的時候就是會出現不一致啊。

除非你消除共享變量,讓每個線程只訪問一個函數內的局部變量, 這些局部變量我們每個線程都會有一份, 函數結束以后就會銷毀,所以線程之間就隔離了,就安全了。

消除共享變量談何容易, 人類使用的很多語言例如C++, Java,那些共享變量大多數一個對象的字段, 你想把字段去掉, 只留下函數, 那類也沒有存在的必要了, 就類似于函數式編程了, 一切都是函數。 有時候我挺羨慕函數式的世界, 那種無狀態應該是一種非常美妙的感覺吧。

2.爭搶吧,線程

既然共享變量是無法消除的,那就想想別的辦法吧, 線程元老院的那幫家伙們哼哧了半天,終于公布了一個方案: 加鎖!

任何線程,只要你想操作一個共享變量,對不起, 先去申請一把鎖, 拿到這把鎖才能讀取x的值 , 修改x的值, 把x寫回內存, ***釋放鎖,讓別人去玩。

元老院設計的這把鎖非常簡單, 類似于一個boolean 變量, boolean lock = false. 誰能搶先把這個變量改成true, 就意味著獲取了這把鎖。

來吧,哥幾個,快來搶吧 !

我運行的時候, 就去檢查lock這個變量是否可以設置為true, 如果被別的家伙給搶到了(已經變成true了), 我就在這里***循環,拼命的搶, 除非我的時間片到了,被迫讓出CPU, 但是我不會阻塞, 還是就緒狀態,等待下一次的調度, 進入CPU繼續搶。

看到某人把它變成false, 我眼疾手快迅速出手, 終于搶到了,趕緊把lock改成true, 這把鎖現在屬于我了, 趕快去干活,干完活要記住把lock 改成false, 讓別的家伙們去搶。

我想正是由于這種***循環的特點, 元老院把他命名為“自旋鎖”吧!

列位看官,可能你已經想到了, 假設有兩個線程,都讀到了lock == false, 都把lock 改成true, 那這個鎖算誰的?

這個問題元老院的大佬們早就考慮到了, 他們和操作系統(我聽說還有硬件)都商量好了, 這個檢測lock是否為false, 以及設置lock 為true 的操作 其實被合并了, 叫做test_and_set(lock), 操作系統鄭重承諾,這是一個不可分割的原子操作, 在這個test_and_set執行的時候,總線都被鎖住了, 別人不能訪問內存, 即使有多個CPU在執行也不會亂掉。

如果你感興趣,可以看看下面的實現, 否則直接無視跳過:

3.改進

有了自旋鎖, 至少可以保證程序的正確運行了, 我們大家都玩的不亦樂乎。

有一天我遇到了一個遞歸函數, 我是挺喜歡遞歸的, 因為邏輯簡單, 只要遞歸的層次別太深, 別搞出棧溢出就好。

這個遞歸函數中需要獲得自旋鎖,做點事情, 然后繼續調用自己, 類似于這樣:

我***次調用doSomething, 獲取了自旋鎖, 然后第二次調用doSomething, 還要獲取自旋鎖, 可是這個鎖已經在我***次調用的時候持有了, 現在第二次調用只有***的等待了!

這下尷尬了, 我進退不得, 自己把自己搞成了死鎖!

看來這個自旋鎖雖然能實現互斥的訪問, 但是不能重新進入同一個函數(簡稱不可重入)啊!

我趕緊把這個問題向元老院做了匯報, 修改方案很快就下來了: 每次成功的申請鎖以后,要記錄下到底是誰申請的, 還要用一個計數器記錄重入的次數, 下一次持有鎖的家伙再次申請鎖只是給計數器加一而已。

釋放的時候也是一樣, 把計數器減一, 如果等于0了才真正的釋放鎖。

可重入性就這么解決了, 但是這么多線程都在那里拼命的搶也不是辦法, 空耗CPU也是巨大的浪費啊。

于是元老院又發布了新的鎖 ReentrantLock, 這個鎖可以重入,如果你搶不到, 不要***循環了, 乖乖的到等待隊列里待著去, 等到鎖被別人釋放了再通知你去搶。(在Java 中最初是synchronzied關鍵字,可以用在一個方法上或者一個代碼塊上, 后來又改進為更加靈活的ReentrantLock)

很快就有線程還抱怨說, 明明是我先發出獲得鎖的申請啊, 為什么隔壁老王卻先拿到了鎖? 這不公平啊,不行,以后得排隊, 先來先得。 好吧, 只好加上一個是否公平的參數。

還有線程說, 我是個急性子,申請鎖的時候只想等待5秒鐘, 5秒之內得不到鎖我就放棄了, 能不能支持? 那就再加上一個參數:等待時間。

4.發揚光大

體會到鎖帶來的甜頭以后, 各種各樣樣的需求紛至沓來:

(1)有時候需要多個線程都獲得同一把鎖,去做一件事情,那怎么辦呢?

沒關系,信號量(Semaphore)出馬,創建信號量的時候得指定一個整數(例如10), 表明同一時刻最多有10個線程可以獲得鎖:

Semaphore lock= new Semaphore(10);

當然每個線程都需要調用lock.aquire(), lock.release()去申請/釋放鎖。

(2)一個線程要寫共享變量, 可是還有幾個線程要同時讀, 怎么辦? 你寫的時候可以鎖住, 但總不能讀的時候也只允許一個線程吧?

只好來一個讀寫鎖了ReadWriteLock, 為了保證可重入性, 元老院體貼的實現了ReentrantReadWriteLock。

(3)一個線程需要等待其他多個線程完工以后才能干活,怎么辦?

CountDownLatch前來救駕, 搞一個計數器,某個線程干完了就把計數器減去1, 如果計數器為0了,那個一直耐心等待的線程就可以開始了。

(4)還有幾個線程必須互相等待, 就像100米賽跑那樣, 所有人都準備好了才能開閘放水, 不,是起跑, 就那就賞你一個CyclicBarrier吧。

【本文為51CTO專欄作者“劉欣”的原創稿件,轉載請通過作者微信公眾號coderising獲取授權】

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

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2021-07-22 09:13:42

Java代碼

2018-05-20 10:09:12

JavaScriptPHPPython

2012-07-24 09:18:39

編程程序員

2023-04-23 10:37:01

CIO執行顧問

2020-11-23 11:11:29

人工智能

2013-09-26 11:18:31

設計

2021-08-26 06:00:29

密碼非對稱加密數據安全

2022-09-15 12:41:43

微服務后端前端

2023-05-23 18:31:14

Rust編程

2018-01-09 04:50:39

2019-10-23 16:39:48

網絡安全綠盟科技

2011-06-10 15:04:41

SEO外鏈

2010-07-12 13:43:48

編程語言

2020-09-01 10:50:17

LinuxSpinlockUbuntu

2023-11-24 11:15:21

協程編程

2013-12-16 15:04:51

多核編程

2013-06-09 08:52:50

哈希表

2013-03-20 10:30:22

2011-06-15 19:17:15

關鍵詞

2018-07-19 19:07:33

語言編程語言程序
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 美日韩精品 | 一区二区三区四区不卡 | 97久久久久久久久 | 日韩国产欧美一区 | 国产在线观看一区二区三区 | av片在线播放 | 亚洲视频www | 成人性视频免费网站 | 久久久精品久久 | 97精品超碰一区二区三区 | 久久久久国产精品 | 午夜小视频在线播放 | 久久久九九| 91偷拍精品一区二区三区 | 黄色在线播放视频 | 欧美性猛交一区二区三区精品 | 欧美日日 | 精品国产一级 | 高清国产一区二区 | 久久久久久久国产 | 盗摄精品av一区二区三区 | 久久小视频 | 亚洲精品久久久久中文字幕欢迎你 | 亚洲国产精品suv | 99精品国产一区二区青青牛奶 | 欧美在线一区二区三区 | 欧美aa在线 | 九九av | 久久成人免费 | 国产一区| av天天看| 国产高清在线精品 | 国产精品一区一区 | 国产在线视频在线观看 | 色播久久久 | 亚洲另类春色偷拍在线观看 | 99久久夜色精品国产亚洲96 | 国产激情一区二区三区 | 久久久久久影院 | 国产精品99久久久久久久久 | 91欧美激情一区二区三区成人 |