日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

Java的ConcurrentHashMap是使用的分段鎖?

來源: 責(zé)編: 時(shí)間:2024-02-01 12:51:54 195觀看
導(dǎo)讀了不起在前兩天的時(shí)候給大家講述了關(guān)于這個(gè) Java 的公平鎖,非公平鎖,共享鎖,獨(dú)占鎖,樂觀鎖,悲觀鎖,遞歸鎖,讀寫鎖,今天我們就再來了解一下其他的鎖,比如,輕量級(jí)鎖,重量級(jí)鎖,偏向鎖,以及分段鎖。輕量級(jí)鎖Java的輕量級(jí)鎖(Lightweight

了不起在前兩天的時(shí)候給大家講述了關(guān)于這個(gè) Java 的公平鎖,非公平鎖,共享鎖,獨(dú)占鎖,樂觀鎖,悲觀鎖,遞歸鎖,讀寫鎖,今天我們就再來了解一下其他的鎖,比如,輕量級(jí)鎖,重量級(jí)鎖,偏向鎖,以及分段鎖。Mav28資訊網(wǎng)——每日最新資訊28at.com

輕量級(jí)鎖

Java的輕量級(jí)鎖(Lightweight Locking)是Java虛擬機(jī)(JVM)中的一種優(yōu)化機(jī)制,用于減少多線程競(jìng)爭(zhēng)時(shí)的性能開銷。在多線程環(huán)境中,當(dāng)多個(gè)線程嘗試同時(shí)訪問共享資源時(shí),通常需要某種形式的同步以防止數(shù)據(jù)不一致。Java提供了多種同步機(jī)制,如synchronized關(guān)鍵字和ReentrantLock,但在高并發(fā)場(chǎng)景下,這些機(jī)制可能導(dǎo)致性能瓶頸。Mav28資訊網(wǎng)——每日最新資訊28at.com

輕量級(jí)鎖是JVM中的一種鎖策略,它在沒有多線程競(jìng)爭(zhēng)的情況下提供了較低的開銷,同時(shí)在競(jìng)爭(zhēng)變得激烈時(shí)能夠自動(dòng)升級(jí)到更重量級(jí)的鎖。這種策略的目標(biāo)是在不需要時(shí)避免昂貴的線程阻塞操作。Mav28資訊網(wǎng)——每日最新資訊28at.com

不過這種鎖并不是通過Java語言直接暴露給開發(fā)者的API,而是JVM在運(yùn)行時(shí)根據(jù)需要自動(dòng)應(yīng)用的。因此,我們不能直接通過Java代碼來實(shí)現(xiàn)一個(gè)輕量級(jí)鎖。Mav28資訊網(wǎng)——每日最新資訊28at.com

但是我們可以使用Java提供的synchronized關(guān)鍵字或java.util.concurrent.locks.Lock接口(及其實(shí)現(xiàn)類,如ReentrantLock)來創(chuàng)建同步代碼塊或方法,這些同步機(jī)制在底層可能會(huì)被JVM優(yōu)化為使用輕量級(jí)鎖。Mav28資訊網(wǎng)——每日最新資訊28at.com

示例代碼:Mav28資訊網(wǎng)——每日最新資訊28at.com

public class LightweightLockExample {        private Object lock = new Object();      private int sharedData;        public void incrementSharedData() {          synchronized (lock) {              sharedData++;          }      }        public int getSharedData() {          synchronized (lock) {              return sharedData;          }      }        public static void main(String[] args) {          LightweightLockExample example = new LightweightLockExample();            // 使用多個(gè)線程來訪問共享數(shù)據(jù)          for (int i = 0; i < 10; i++) {              new Thread(() -> {                  for (int j = 0; j < 1000; j++) {                      example.incrementSharedData();                  }              }).start();          }            // 等待所有線程執(zhí)行完畢          try {              Thread.sleep(2000);          } catch (InterruptedException e) {              e.printStackTrace();          }            // 輸出共享數(shù)據(jù)的最終值          System.out.println("Final shared data value: " + example.getSharedData());      }  }

這個(gè)示例中的同步塊在JVM內(nèi)部可能會(huì)使用輕量級(jí)鎖(具體是否使用取決于JVM的實(shí)現(xiàn)和運(yùn)行時(shí)環(huán)境)Mav28資訊網(wǎng)——每日最新資訊28at.com

在這個(gè)例子中,我們有一個(gè)sharedData變量,多個(gè)線程可能會(huì)同時(shí)訪問它。我們使用synchronized塊來確保每次只有一個(gè)線程能夠修改sharedData。在JVM內(nèi)部,這些synchronized塊可能會(huì)使用輕量級(jí)鎖來優(yōu)化同步性能。Mav28資訊網(wǎng)——每日最新資訊28at.com

請(qǐng)注意,這個(gè)例子只是為了演示如何使用synchronized關(guān)鍵字,并不能保證JVM一定會(huì)使用輕量級(jí)鎖。實(shí)際上,JVM可能會(huì)根據(jù)運(yùn)行時(shí)的情況選擇使用偏向鎖、輕量級(jí)鎖或重量級(jí)鎖。Mav28資訊網(wǎng)——每日最新資訊28at.com

重量級(jí)鎖

在Java中,重量級(jí)鎖(Heavyweight Locking)是相對(duì)于輕量級(jí)鎖而言的,它涉及到線程阻塞和操作系統(tǒng)級(jí)別的線程調(diào)度。當(dāng)輕量級(jí)鎖或偏向鎖不足以解決線程間的競(jìng)爭(zhēng)時(shí),JVM會(huì)升級(jí)鎖為重量級(jí)鎖。Mav28資訊網(wǎng)——每日最新資訊28at.com

重量級(jí)鎖通常是通過操作系統(tǒng)提供的互斥原語(如互斥量、信號(hào)量等)來實(shí)現(xiàn)的。當(dāng)一個(gè)線程嘗試獲取已經(jīng)被其他線程持有的重量級(jí)鎖時(shí),它會(huì)被阻塞(即掛起),直到持有鎖的線程釋放該鎖。在阻塞期間,線程不會(huì)消耗CPU資源,但會(huì)導(dǎo)致上下文切換的開銷,因?yàn)椴僮飨到y(tǒng)需要保存和恢復(fù)線程的上下文信息。Mav28資訊網(wǎng)——每日最新資訊28at.com

在Java中,synchronized關(guān)鍵字和java.util.concurrent.locks.ReentrantLock都可以導(dǎo)致重量級(jí)鎖的使用,尤其是在高并發(fā)和激烈競(jìng)爭(zhēng)的場(chǎng)景下。Mav28資訊網(wǎng)——每日最新資訊28at.com

我們來看看使用synchronized可能會(huì)涉及到重量級(jí)鎖的代碼:Mav28資訊網(wǎng)——每日最新資訊28at.com

public class HeavyweightLockExample {        private final Object lock = new Object();      private int counter;        public void increment() {          synchronized (lock) {              counter++;          }      }        public int getCounter() {          synchronized (lock) {              return counter;          }      }        public static void main(String[] args) {          HeavyweightLockExample example = new HeavyweightLockExample();            // 創(chuàng)建多個(gè)線程同時(shí)訪問共享資源          for (int i = 0; i < 10; i++) {              new Thread(() -> {                  for (int j = 0; j < 10000; j++) {                      example.increment();                  }              }).start();          }            // 等待所有線程完成          try {              Thread.sleep(2000);          } catch (InterruptedException e) {              e.printStackTrace();          }            // 輸出計(jì)數(shù)器的值          System.out.println("Final counter value: " + example.getCounter());      }  }

在這個(gè)示例中,多個(gè)線程同時(shí)訪問counter變量,并使用synchronized塊來確保每次只有一個(gè)線程能夠修改它。如果線程間的競(jìng)爭(zhēng)非常激烈,JVM可能會(huì)將synchronized塊內(nèi)部的鎖升級(jí)為重量級(jí)鎖。Mav28資訊網(wǎng)——每日最新資訊28at.com

我們說的是可能哈,畢竟內(nèi)部操作還是由 JVM 具體來操控的。Mav28資訊網(wǎng)——每日最新資訊28at.com

我們?cè)賮砜纯催@個(gè)ReentrantLock來實(shí)現(xiàn):Mav28資訊網(wǎng)——每日最新資訊28at.com

import java.util.concurrent.locks.ReentrantLock;    public class ReentrantLockExample {        private final ReentrantLock lock = new ReentrantLock();      private int counter;        public void increment() {          lock.lock(); // 獲取鎖          try {              counter++;          } finally {              lock.unlock(); // 釋放鎖          }      }        public int getCounter() {          return counter;      }        public static void main(String[] args) {          // 類似上面的示例,創(chuàng)建線程并訪問共享資源      }  }

在這個(gè)示例中,ReentrantLock被用來同步對(duì)counter變量的訪問。如果鎖競(jìng)爭(zhēng)激烈,ReentrantLock內(nèi)部可能會(huì)使用重量級(jí)鎖。Mav28資訊網(wǎng)——每日最新資訊28at.com

需要注意的是,重量級(jí)鎖的使用會(huì)帶來較大的性能開銷,因此在設(shè)計(jì)并發(fā)系統(tǒng)時(shí)應(yīng)盡量通過減少鎖競(jìng)爭(zhēng)、使用更細(xì)粒度的鎖、使用無鎖數(shù)據(jù)結(jié)構(gòu)等方式來避免重量級(jí)鎖的使用。Mav28資訊網(wǎng)——每日最新資訊28at.com

偏向鎖

在Java中,偏向鎖(Biased Locking)是Java虛擬機(jī)(JVM)為了提高無競(jìng)爭(zhēng)情況下的性能而引入的一種鎖優(yōu)化機(jī)制。它的基本思想是,如果一個(gè)線程獲得了鎖,那么鎖就進(jìn)入偏向模式,此時(shí)Mark Word的結(jié)構(gòu)也變?yōu)槠蜴i結(jié)構(gòu),當(dāng)這個(gè)線程再次請(qǐng)求鎖時(shí),無需再做任何同步操作,即獲取鎖的過程只需要檢查Mark Word的鎖標(biāo)記位為偏向鎖以及當(dāng)前線程ID等于Mark Word的Thread ID即可,這樣就省去了大量有關(guān)鎖申請(qǐng)的操作。Mav28資訊網(wǎng)——每日最新資訊28at.com

他和輕量級(jí)鎖和重量級(jí)鎖一樣,并不是直接通過Java代碼來控制的,而是由JVM在運(yùn)行時(shí)自動(dòng)進(jìn)行的。因此,你不能直接編寫Java代碼來顯式地使用偏向鎖。不過,你可以編寫一個(gè)使用synchronized關(guān)鍵字的簡(jiǎn)單示例,JVM可能會(huì)自動(dòng)將其優(yōu)化為使用偏向鎖(取決于JVM的實(shí)現(xiàn)和運(yùn)行時(shí)的配置)。Mav28資訊網(wǎng)——每日最新資訊28at.com

示例代碼:Mav28資訊網(wǎng)——每日最新資訊28at.com

public class BiasedLockingExample {        // 這個(gè)對(duì)象用作同步的鎖      private final Object lock = new Object();            // 共享資源      private int sharedData;        // 使用synchronized關(guān)鍵字進(jìn)行同步的方法      public synchronized void synchronizedMethod() {          sharedData++;      }        // 使用對(duì)象鎖進(jìn)行同步的方法      public void lockedMethod() {          synchronized (lock) {              sharedData += 2;          }      }        public static void main(String[] args) throws InterruptedException {          // 創(chuàng)建示例對(duì)象          BiasedLockingExample example = new BiasedLockingExample();            // 使用Lambda表達(dá)式和Stream API創(chuàng)建并啟動(dòng)多個(gè)線程          IntStream.range(0, 10).forEach(i -> {              new Thread(() -> {                  // 每個(gè)線程多次調(diào)用同步方法                  for (int j = 0; j < 10000; j++) {                      example.synchronizedMethod();                      example.lockedMethod();                  }              }).start();          });            // 讓主線程睡眠一段時(shí)間,等待其他線程執(zhí)行完畢          Thread.sleep(2000);            // 輸出共享數(shù)據(jù)的最終值          System.out.println("Final sharedData value: " + example.sharedData);      }  }

在這個(gè)示例中,我們有一個(gè)BiasedLockingExample類,它有兩個(gè)同步方法:synchronizedMethod和lockedMethod。synchronizedMethod是一個(gè)實(shí)例同步方法,它隱式地使用this作為鎖對(duì)象。lockedMethod是一個(gè)使用顯式對(duì)象鎖的方法,它使用lock對(duì)象作為鎖。Mav28資訊網(wǎng)——每日最新資訊28at.com

當(dāng)多個(gè)線程調(diào)用這些方法時(shí),JVM可能會(huì)觀察到只有一個(gè)線程在反復(fù)獲取同一個(gè)鎖,并且沒有其他線程競(jìng)爭(zhēng)該鎖。在這種情況下,JVM可能會(huì)將鎖偏向到這個(gè)線程,以減少獲取和釋放鎖的開銷。Mav28資訊網(wǎng)——每日最新資訊28at.com

然而,請(qǐng)注意以下幾點(diǎn):Mav28資訊網(wǎng)——每日最新資訊28at.com

  • 偏向鎖的使用是由JVM動(dòng)態(tài)決定的,你不能強(qiáng)制JVM使用偏向鎖。
  • 在高并發(fā)環(huán)境下,如果鎖競(jìng)爭(zhēng)激烈,偏向鎖可能會(huì)被撤銷并升級(jí)到更重的鎖狀態(tài),如輕量級(jí)鎖或重量級(jí)鎖。
  • 偏向鎖適用于鎖被同一個(gè)線程多次獲取的場(chǎng)景。如果鎖被多個(gè)線程頻繁地爭(zhēng)用,偏向鎖可能不是最優(yōu)的選擇。

由于偏向鎖是透明的優(yōu)化,因此你不需要在代碼中做任何特殊的事情來利用它。只需編寫正常的同步代碼,讓JVM來決定是否應(yīng)用偏向鎖優(yōu)化。Mav28資訊網(wǎng)——每日最新資訊28at.com

分段鎖

在Java中,"分段鎖"并不是一個(gè)官方的術(shù)語,但它通常被用來描述一種并發(fā)控制策略,其中數(shù)據(jù)結(jié)構(gòu)或資源被分成多個(gè)段,并且每個(gè)段都有自己的鎖。這種策略的目的是提高并發(fā)性能,允許多個(gè)線程同時(shí)訪問不同的段,而不會(huì)相互阻塞。Mav28資訊網(wǎng)——每日最新資訊28at.com

而在 Java 里面的經(jīng)典例子則是ConcurrentHashMap,在早期的ConcurrentHashMap實(shí)現(xiàn)中,內(nèi)部采用了一個(gè)稱為Segment的類來表示哈希表的各個(gè)段,每個(gè)Segment對(duì)象都持有一個(gè)鎖。這種設(shè)計(jì)允許多個(gè)線程同時(shí)讀寫哈希表的不同部分,而不會(huì)產(chǎn)生鎖競(jìng)爭(zhēng),從而提高了并發(fā)性能。Mav28資訊網(wǎng)——每日最新資訊28at.com

然而,需要注意的是,從Java 8開始,ConcurrentHashMap的內(nèi)部實(shí)現(xiàn)發(fā)生了重大變化。它不再使用Segment,而是采用了一種基于CAS(Compare-and-Swap)操作和Node數(shù)組的新設(shè)計(jì),以及紅黑樹來處理哈希沖突。這種新設(shè)計(jì)提供了更高的并發(fā)性和更好的性能。盡管如此,"分段鎖"這個(gè)概念仍然可以用來描述這種將數(shù)據(jù)結(jié)構(gòu)分成多個(gè)可獨(dú)立鎖定的部分的通用策略。Mav28資訊網(wǎng)——每日最新資訊28at.com

我們看一個(gè)分段鎖實(shí)現(xiàn)安全計(jì)數(shù)器的代碼:Mav28資訊網(wǎng)——每日最新資訊28at.com

import java.util.concurrent.locks.Lock;  import java.util.concurrent.locks.ReentrantLock;    public class SegmentedCounter {      private final int size;      private final Lock[] locks;      private final int[] counters;        public SegmentedCounter(int size) {          this.size = size;          this.locks = new Lock[size];          this.counters = new int[size];          for (int i = 0; i < size; i++) {              locks[i] = new ReentrantLock();          }      }        public void increment(int index) {          locks[index].lock();          try {              counters[index]++;          } finally {              locks[index].unlock();          }      }        public int getValue(int index) {          locks[index].lock();          try {              return counters[index];          } finally {              locks[index].unlock();          }      }  }

在這個(gè)例子中,SegmentedCounter類有一個(gè)counters數(shù)組和一個(gè)locks數(shù)組。每個(gè)計(jì)數(shù)器都有一個(gè)與之對(duì)應(yīng)的鎖,這使得線程可以獨(dú)立地更新不同的計(jì)數(shù)器,而不會(huì)相互干擾。當(dāng)然,這個(gè)簡(jiǎn)單的例子并沒有考慮一些高級(jí)的并發(fā)問題,比如鎖的粒度選擇、鎖爭(zhēng)用和公平性等問題。在實(shí)際應(yīng)用中,你可能需要根據(jù)具體的需求和性能目標(biāo)來調(diào)整設(shè)計(jì)。Mav28資訊網(wǎng)——每日最新資訊28at.com

所以,你學(xué)會(huì)了么?Mav28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-70469-0.htmlJava的ConcurrentHashMap是使用的分段鎖?

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 字節(jié)碼增強(qiáng)技術(shù),不止有 Java Proxy、 Cglib 和 Javassist 還有 Byte Buddy

下一篇: 十個(gè)Python編程小技巧

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 主站蜘蛛池模板: 元朗区| 连江县| 紫阳县| 扶沟县| 道真| 资兴市| 罗城| 赫章县| 鹰潭市| 定州市| 南华县| 张北县| 新安县| 龙泉市| 綦江县| 抚远县| 汕头市| 九龙县| 手机| 温州市| 寻乌县| 扬中市| 嘉定区| 昌吉市| 江达县| 潜江市| 宝丰县| 苍南县| 唐山市| 雷山县| 定南县| 柘城县| 锦州市| 绥德县| 宜黄县| 武威市| 资源县| 报价| 周口市| 南充市| 北安市|