日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

来说一说你对锁都怎么分类?

發布時間:2024/9/30 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 来说一说你对锁都怎么分类? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

悲觀鎖和樂觀鎖

我覺得悲觀鎖和樂觀鎖更多的是指一種思想,實現鎖的不同方式。數據庫、git都有不同的對應悲觀鎖和樂觀鎖思想的應用.

  • 悲觀鎖一般是互斥鎖,
    但是1.阻塞和喚醒會帶來性能損耗,要去切換用戶態切換狀態,查看要喚醒的線程等等;2.而且可能導致永久阻塞,比如發生了無限循環,死鎖,那么阻塞等待獲取鎖的線程就可能永久等待了。3.還可能導致線程優先級混亂。適合并發多競爭很激烈的情況,代碼復雜 或者循環量大

    java中最常見的悲觀鎖就是synchronized和lock類,但是注意,synchronized引入了偏向鎖、輕量級鎖等優化措施,readWriteLock在讀的時候是共享鎖,寫的時候是獨占鎖??傮w上來說還是得先拿到鎖,才能執行

  • 樂觀鎖是非互斥鎖,
    認為自己在操作的時候不會有其他線程干擾,所以不會鎖住操作對象。更新的時候去再去比較對象數據是否被修改過,如果沒修改過最好,如果發生了修改,就要選擇放棄,拋棄,重試等策略。適合并發寫入少,讀取多的情況,提高讀取的性能

    樂觀鎖基本都是基于CAS算法實現的,注意ABA問題,可以加版本號解決。有原子類,并發容器

共享鎖和獨占鎖

獨占鎖 ,又稱排它鎖、獨享鎖
共享鎖,又稱讀鎖,獲取到鎖后可以查看但不能修改刪除。為什么要這樣設計呢 ?是因為很多線程讀并不會造成線程安全問題,所以如果允許多個線程來讀,就可以提高性能。

ReentrantReadWriteLock讀寫鎖,其中讀鎖是共享鎖,寫鎖時獨占鎖。
要么是多讀,要么是一寫。更具體點說就是,多個線程讀沒問題;以如果已經有線程在讀,那么其他線程申請寫鎖則必須要等待釋放讀鎖;如果一個線程已經在寫,那么其他線程申請讀或寫都必須要等待釋放寫鎖。

ReentrantReadWriteLock公平鎖:不允許任何插隊,不管寫鎖還是讀鎖,只要隊列里已經有線程了就應該阻塞等待
ReentrantReadWriteLock非公平:

  • 寫鎖可以隨時插隊,即不需要阻塞
  • 讀鎖僅在等待隊列中頭結點不是寫線程時可以插隊:
    舉個例子:假設線程2和線程4正在同時讀,線程3想要寫入,所以進入了等待隊列且在頭結點。然后線程5過來想要讀,那么此時允不允許線程5去同時讀呢?
    如果允許線程5插隊讀,則可能不停的有線程來插隊讀,寫的線程就可能饑餓,所以ReentrantReadWriteLock不允許插隊讀,如果有寫線程在排隊則必須進入隊列排隊

ReentrantReadWriteLock支持寫鎖降級為讀鎖,但不支持讀鎖升級為寫鎖(避免死鎖)。
為什么需要鎖降級?比如一個任務剛開始需要寫鎖拿到某個日志文件,但是后續都只需要讀就行,顯然如果還是一直持有寫鎖性能就會差很多,如果可以降級為讀鎖,就能允許其他線程一起讀,性能就會好很多。
為什么不支持鎖升級為寫鎖呢?可能造成死鎖,比如兩個線程同時準備升級為寫鎖

公平鎖和非公平鎖

公平鎖指的是完全按照線程請求的順序來分配鎖;非公平是不完全按照線程請求順序,注意不是完全隨機的,在一定情況下可以插隊。

為什么要設計非公平鎖呢?
非公平可以避免去喚醒線程時的空檔期,提高使用性能,提高吞吐量。但有可能造成線程饑餓,即某些線程一直都拿不到鎖

synchronize是非公平鎖,ReentrantLock默認是非公平鎖,但也可以構造公平鎖。其實對應源碼的實現很簡單,就是在獲取鎖時是否放入隊列

//非公平鎖 的嘗試獲取final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}//公平鎖的 嘗試獲取protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {//唯一的區別就在于這里,如果鎖沒被任何一個線程拿到,不像上面直接去cas爭搶,//而是會hasQueuedPredecessors去判斷是否有其他線程等待的時間更長if (!hasQueuedPredecessors() &&compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0)throw new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}

注意tryLock是個特例sync.nonfairTryAcquire(1);,即使設置的公平鎖,也會非公平的去爭搶鎖。

可重入鎖和不可重入鎖

什么是可重入鎖呢?簡單來說,就是一個線程可以多次拿到一個鎖,Reentrant和synchronize都是可重入鎖
有什么好處?
避免死鎖,如果不是可重入鎖,你拿到鎖了,然后你想進入鎖的另一個方法,你拿不到了!可能造成死鎖
避免了重復的加鎖和解鎖

自旋鎖和阻塞鎖

也就是準備獲取鎖的線程無法獲取到鎖時,就先自旋,不用阻塞,避免了線程切換帶來的開銷。但是可能帶來CPU的浪費,因此有自適應自旋鎖。
synchronize引入的輕量級鎖就是自旋鎖的最好應用。適合少量線程競爭,且每個線程持有鎖的時間不長的情況

可中斷鎖和不可中斷鎖

如果某個線程獲取到了鎖正在執行,線程B正在等待獲取鎖,可是由于等待時間過長,我們可以中斷線程B,這就是可中斷鎖。
synchronize就是不可中斷鎖,lock是可中斷鎖,try( time)和lockInterruptibly都能響應中斷。

鎖優化

  • JVM提供了鎖粗化和鎖消除來優化鎖
  • 我們在并發編程時要注意,盡量縮小同步代碼塊的范圍,盡量不要鎖住方法,減少加鎖的次數。鎖中不要再包含鎖,容易造成死鎖。選擇合適的鎖和工具類

總結

以上是生活随笔為你收集整理的来说一说你对锁都怎么分类?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。