中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

百度怎么做自己的網(wǎng)站怎么在百度上發(fā)帖推廣

百度怎么做自己的網(wǎng)站,怎么在百度上發(fā)帖推廣,建設(shè)銀行的官方網(wǎng)站紀(jì)念幣,做程序的軟件文章導(dǎo)讀 引言考點(diǎn)1. CAS 指令(重點(diǎn))一、什么是CAS二、CAS 的優(yōu)點(diǎn)三、CAS 的缺點(diǎn)四、ABA問(wèn)題五、相關(guān)面試題 考點(diǎn)2. 信號(hào)量(semaphore)一、基本概念二、信號(hào)量的主要操作三、信號(hào)量的應(yīng)用四、相關(guān)面試題 考點(diǎn)3、CountDownLatch 類…

文章導(dǎo)讀

  • 引言
  • 考點(diǎn)1. CAS 指令(重點(diǎn))
      • 一、什么是CAS
      • 二、CAS 的優(yōu)點(diǎn)
      • 三、CAS 的缺點(diǎn)
      • 四、ABA問(wèn)題
      • 五、相關(guān)面試題
  • 考點(diǎn)2. 信號(hào)量(semaphore)
      • 一、基本概念
      • 二、信號(hào)量的主要操作
      • 三、信號(hào)量的應(yīng)用
      • 四、相關(guān)面試題
  • 考點(diǎn)3、CountDownLatch 類
      • 一、主要用途
      • 二、主要方法
      • 三、示例
  • 考點(diǎn)4、Callable 接口
      • Callable 與 Runnable 的主要區(qū)別
      • 使用場(chǎng)景
      • 示例
      • 相關(guān)面試題
  • 考點(diǎn)5、多線程下的數(shù)據(jù)結(jié)構(gòu)
    • 一、多線程環(huán)境使用ArrayList
    • 二、多線程環(huán)境下使用哈希表
      • 1、Hashtable
      • 2、ConcurrentHashMap(重點(diǎn))
      • 相關(guān)面試題
  • 考點(diǎn)五、其他常見(jiàn)面試題

引言

本篇文章總結(jié)了多線程中面試頻率比較高的考點(diǎn),內(nèi)容可能比較瑣碎,但是如果能夠堅(jiān)持看完,注意總結(jié)積累,相信對(duì)面試會(huì)有很大幫助。多線程內(nèi)容較多,用一篇文章寫(xiě)完可能篇幅過(guò)長(zhǎng),我打算用兩篇文章來(lái)總結(jié),本篇主要寫(xiě)的是多線程中輔助加鎖的數(shù)據(jù)結(jié)構(gòu)和指令,下一篇主要講的是鎖策略。

考點(diǎn)1. CAS 指令(重點(diǎn))

一、什么是CAS

CAS(Compare-and-Swap)是一種用于實(shí)現(xiàn)多線程同步的原子指令。它涉及到三個(gè)操作數(shù):內(nèi)存位置(V)、預(yù)期原值(A)和新值(B)。如果內(nèi)存位置的值與預(yù)期原值相匹配,那么處理器會(huì)自動(dòng)將該位置值更新為新值,這個(gè)操作是原子的。

CAS 操作包含三個(gè)關(guān)鍵動(dòng)作:

  1. 比較(Compare):將內(nèi)存位置的值與預(yù)期原值進(jìn)行比較。
  2. 交換(Swap):如果比較相等,那么處理器會(huì)自動(dòng)將該內(nèi)存位置的值更新為新值。
  3. 原子性(Atomicity):上述整個(gè)比較和交換的操作是原子的,即該操作在執(zhí)行過(guò)程中不會(huì)被其他線程的操作打斷。
    在這里插入圖片描述

CAS 指令一般是基于硬件實(shí)現(xiàn)的,在 Intel 處理器中,它可以通過(guò) LOCK 前綴的 CMPXCHG 指令來(lái)實(shí)現(xiàn)。在 Java 中,CAS 操作被廣泛用于實(shí)現(xiàn)非阻塞算法,如原子變量類java.util.concurrent.atomic 包下的類)中的 getAndIncrementcompareAndSet 等方法都是基于 CAS 實(shí)現(xiàn)的。

二、CAS 的優(yōu)點(diǎn)

  • 非阻塞算法:CAS 允許線程在不進(jìn)入阻塞狀態(tài)的情況下進(jìn)行并發(fā)操作,這有助于減少線程切換的開(kāi)銷,提高系統(tǒng)的并發(fā)性能。
  • 無(wú)需使用鎖:在多個(gè)線程競(jìng)爭(zhēng)同一個(gè)資源時(shí),傳統(tǒng)的鎖機(jī)制可能會(huì)導(dǎo)致線程阻塞,而 CAS 可以在不依賴鎖的情況下實(shí)現(xiàn)線程間的同步。

三、CAS 的缺點(diǎn)

  • 循環(huán)時(shí)間長(zhǎng)開(kāi)銷大:如果 CAS 操作一直不成功,那么線程會(huì)一直處于自旋狀態(tài)(返回失敗并持續(xù)重試),這會(huì)增加 CPU 的負(fù)擔(dān)。
  • 只能保證一個(gè)共享變量的原子操作當(dāng)需要對(duì)多個(gè)共享變量進(jìn)行操作時(shí),CAS 就無(wú)法保證操作的原子性了。這種情況下,需要使用鎖或其他同步機(jī)制來(lái)保證操作的原子性。

四、ABA問(wèn)題

  • 情景

    • 假設(shè)小明有存款1000元,他去ATM機(jī)上取100元,服務(wù)器產(chǎn)生了兩個(gè)線程處理。線程1執(zhí)行完存款變?yōu)?00,線程2CAS指令比較失敗,無(wú)法執(zhí)行。
      在這里插入圖片描述
    • 就在小明取錢的時(shí)候,小明的爸爸給小明的銀行賬戶轉(zhuǎn)了100元,產(chǎn)生了線程3。如果線程3是在線程1執(zhí)行后才產(chǎn)生的,那么就會(huì)出現(xiàn)存款從 1000 -> 900 -> 1000 的過(guò)程,于是再執(zhí)行線程2的CAS指令就會(huì)成功。本來(lái)小明只想取100元,現(xiàn)在取錢操作執(zhí)行了兩次,取出了200元!
      在這里插入圖片描述
  • 定義

    在CAS操作中,線程會(huì)首先讀取某個(gè)內(nèi)存位置的值(我們稱之為預(yù)期值A(chǔ)),然后執(zhí)行CAS操作,嘗試將該內(nèi)存位置的值修改為新的值(我們稱之為B),但前提是內(nèi)存位置的值必須仍然是預(yù)期值A(chǔ)。如果在讀取值和嘗試修改值之間,有其他線程修改了該內(nèi)存位置的值(比如從A改為了B,然后又改回了A),那么CAS操作會(huì)錯(cuò)誤地認(rèn)為該值沒(méi)有變化,從而成功執(zhí)行,這就會(huì)導(dǎo)致ABA問(wèn)題。

    在以上情景中,存款從1000變900再變成1000的過(guò)程所導(dǎo)致的取錢兩次的BUG就是ABA問(wèn)題。

  • 解決方法
    給要修改的值, 引?版本號(hào). 在 CAS ?較數(shù)據(jù)當(dāng)前值和舊值的同時(shí), 也要?較版本號(hào)是否符合預(yù)期。例如:
    給存款引入版本號(hào),每次執(zhí)行線程時(shí)版本號(hào)加1.
    在這里插入圖片描述
    版本號(hào)為1,線程1執(zhí)行扣款成功,存款為900,版本號(hào)+1變?yōu)?,線程3執(zhí)行存入成功,存款為1000,版本號(hào)+1變?yōu)?,線程2執(zhí)行,版本號(hào)與之前讀取的不同,執(zhí)行失敗。

五、相關(guān)面試題

  1. 講解下你??理解的 CAS 機(jī)制。
  2. ABA問(wèn)題怎么解決?

忠告:相關(guān)面試題的答案我不會(huì)給出,讀者應(yīng)自己總結(jié)積累,盲目背誦答案已經(jīng)過(guò)時(shí),面試場(chǎng)上的八股文已被千變?nèi)f化的情景題目所取代,只有自己總結(jié)積累經(jīng)驗(yàn)和知識(shí)才能應(yīng)對(duì)變化,才能讓面試官青睞!

考點(diǎn)2. 信號(hào)量(semaphore)

一、基本概念

  • 定義:信號(hào)量是一個(gè)非負(fù)整數(shù),用于表示某種資源的數(shù)量。它有兩個(gè)主要操作:P(等待)和V(釋放)。
  • 作用:實(shí)現(xiàn)任務(wù)之間的同步或臨界資源的互斥訪問(wèn),常用于協(xié)助一組相互競(jìng)爭(zhēng)的任務(wù)來(lái)訪問(wèn)臨界資源。

二、信號(hào)量的主要操作

  1. P(等待)操作

    • 當(dāng)一個(gè)進(jìn)程或線程需要訪問(wèn)共享資源時(shí),它會(huì)嘗試執(zhí)行P操作。
    • 如果信號(hào)量的值大于0,表示資源可用,進(jìn)程或線程可以繼續(xù)訪問(wèn)資源,并將信號(hào)量的值減1。
    • 如果信號(hào)量的值等于0,表示資源已被占用,進(jìn)程或線程會(huì)被阻塞,直到信號(hào)量的值變?yōu)檎龜?shù)。
  2. V(釋放)操作

    • 當(dāng)一個(gè)進(jìn)程或線程完成對(duì)共享資源的訪問(wèn)時(shí),它會(huì)執(zhí)行V操作,將信號(hào)量的值加1。
    • 如果有其他等待進(jìn)程被阻塞,它們中的一個(gè)將被喚醒并獲得對(duì)資源的訪問(wèn)權(quán)限。

代碼示例

    public static void main(String[] args) {// 信號(hào)量為4,表明有四個(gè)資源待訪問(wèn)Semaphore semaphore = new Semaphore(4);// 寫(xiě)一個(gè)線程訪問(wèn)訪問(wèn)資源Thread t = new Thread(() -> {try {// accquire方法表示P操作semaphore.acquire();// do something ...Thread.sleep(1000);// release方法表示V操作semaphore.release();} catch(InterruptedException e){e.printStackTrace();}});t.start();}

三、信號(hào)量的應(yīng)用

信號(hào)量在操作系統(tǒng)和并發(fā)編程中有著廣泛的應(yīng)用,包括但不限于:

  1. 進(jìn)程同步:控制多個(gè)進(jìn)程的執(zhí)行順序,保證數(shù)據(jù)的正確處理。
  2. 臨界資源的互斥訪問(wèn):保護(hù)共享資源,防止數(shù)據(jù)競(jìng)爭(zhēng)和沖突。
  3. 生產(chǎn)者-消費(fèi)者問(wèn)題:在生產(chǎn)者-消費(fèi)者模型中,通過(guò)信號(hào)量來(lái)控制資源的生產(chǎn)和消費(fèi)。
  4. 線程池管理:控制線程池中的線程數(shù)量,以控制系統(tǒng)的負(fù)載。
  5. 順序控制:確保多個(gè)任務(wù)按照特定的順序執(zhí)行。

綜上所述,信號(hào)量是一種重要的同步機(jī)制,通過(guò)合理地控制信號(hào)量的值,可以實(shí)現(xiàn)對(duì)共享資源的互斥訪問(wèn)和同步操作,從而避免并發(fā)編程中的常見(jiàn)問(wèn)題。

四、相關(guān)面試題

  1. 簡(jiǎn)單解釋一下什么是信號(hào)量?
  2. 什么場(chǎng)景下會(huì)使用到信號(hào)量?

考點(diǎn)3、CountDownLatch 類

CountDownLatch 是 Java 并發(fā)包 java.util.concurrent 中的一個(gè)非常有用的同步輔助類,它允許一個(gè)或多個(gè)線程等待一組其他線程完成操作。這個(gè)類通過(guò)讓一個(gè)或多個(gè)線程等待其他線程完成一組操作來(lái)協(xié)調(diào)線程。CountDownLatch 初始化時(shí)設(shè)置一個(gè)計(jì)數(shù)器(count),這個(gè)計(jì)數(shù)器代表等待完成的操作的數(shù)量。

一、主要用途

  • 等待多個(gè)線程完成CountDownLatch 允許一個(gè)或多個(gè)線程等待其他一組線程完成它們的任務(wù)。例如,在啟動(dòng)多個(gè)線程進(jìn)行并行計(jì)算時(shí),你可能希望等待所有線程都完成計(jì)算后再繼續(xù)執(zhí)行后續(xù)操作。
  • 性能優(yōu)化:通過(guò)并行處理,可以提高應(yīng)用程序的響應(yīng)速度和吞吐量。CountDownLatch 可以幫助在并行處理完成后同步后續(xù)操作。

二、主要方法

  • CountDownLatch(int count):構(gòu)造函數(shù),初始化計(jì)數(shù)器值為給定的 count 值。
  • void await():使當(dāng)前線程在鎖存器倒計(jì)數(shù)至零之前一直處于等待狀態(tài),除非線程被中斷。
  • void await(long timeout, TimeUnit unit):使當(dāng)前線程在鎖存器倒計(jì)數(shù)至零之前一直處于等待狀態(tài),或者從當(dāng)前時(shí)間起已經(jīng)過(guò)了指定的等待時(shí)間,或者線程被中斷。
  • void countDown():遞減鎖存器的計(jì)數(shù),如果計(jì)數(shù)到達(dá)零,則釋放所有等待的線程。

三、示例

下面是一個(gè)簡(jiǎn)單的示例,展示了如何使用 CountDownLatch 來(lái)等待一組線程完成它們的任務(wù)。

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class CountDownLatchExample {public static void main(String[] args) throws InterruptedException {int taskCount = 5;ExecutorService executor = Executors.newFixedThreadPool(taskCount);CountDownLatch latch = new CountDownLatch(taskCount);for (int i = 0; i < taskCount; i++) {executor.submit(() -> {try {// 模擬任務(wù)執(zhí)行Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}latch.countDown(); // 完成任務(wù),減少計(jì)數(shù)器});}// 等待所有任務(wù)完成latch.await();System.out.println("所有任務(wù)完成");executor.shutdown();}
}

在這個(gè)示例中,我們創(chuàng)建了一個(gè)包含 5 個(gè)任務(wù)的線程池。每個(gè)任務(wù)完成后,都會(huì)調(diào)用 countDown() 方法來(lái)減少 CountDownLatch 的計(jì)數(shù)器。主線程通過(guò)調(diào)用 await() 方法等待,直到計(jì)數(shù)器的值達(dá)到 0,即所有任務(wù)都已完成。然后,主線程繼續(xù)執(zhí)行并打印出 “所有任務(wù)完成”。

考點(diǎn)4、Callable 接口

在Java中,Callable 接口是Java并發(fā)API的一部分,它位于 java.util.concurrent 包中。與 Runnable 接口不同,Callable 接口可以返回一個(gè)結(jié)果,并且可能拋出一個(gè)異常。這使得 Callable 接口非常適合用于那些需要返回值的并發(fā)任務(wù)。

Callable 接口的定義如下:

@FunctionalInterface
public interface Callable<V> {/*** Computes a result, or throws an exception if unable to do so.** @return computed result* @throws Exception if unable to compute a result*/V call() throws Exception;
}

Callable 與 Runnable 的主要區(qū)別

  1. 返回值Runnable 接口的 run 方法沒(méi)有返回值,而 Callable 接口的 call 方法可以返回一個(gè)泛型類型的值。
  2. 異常處理Runnablerun 方法不允許拋出受檢查的異常(checked exceptions),而 Callablecall 方法可以。如果 call 方法拋出了一個(gè)異常,這個(gè)異常將被封裝在一個(gè) ExecutionException 中,這個(gè)異常是由 Future.get() 方法拋出的。

使用場(chǎng)景

當(dāng)你需要執(zhí)行一個(gè)任務(wù),并且這個(gè)任務(wù)完成后需要返回一個(gè)結(jié)果時(shí),就可以使用 Callable。例如,你可能需要從遠(yuǎn)程服務(wù)器獲取數(shù)據(jù),或者執(zhí)行一些計(jì)算并返回結(jié)果。

示例

創(chuàng)建線程計(jì)算 1 + 2 + 3 + … + 1000,

使用 Run 版本

  • 創(chuàng)建?個(gè)類 Result,包含?個(gè) sum 表示最終結(jié)果, lock 表?線程同步使?的鎖對(duì)象。

  • main ?法中先創(chuàng)建 Result 實(shí)例, 然后創(chuàng)建?個(gè)線程 t. 在線程內(nèi)部計(jì)算 1 + 2 + 3 + … + 1000.

  • 主線程同時(shí)使? wait 等待線程 t 計(jì)算結(jié)束. (注意, 如果執(zhí)行到 wait 之前, 線程 t 已經(jīng)計(jì)算完了, 就不必等待了)。

  • 當(dāng)線程 t 計(jì)算完畢后, 通過(guò) notify 喚醒主線程, 主線程再打印結(jié)果.

public class Demo18 {static class Result {public int sum = 0;public Object lock = new Object();}public static void main(String[] args) throws InterruptedException {Result result = new Result();Thread t = new Thread() {@Overridepublic void run() {int sum = 0;for (int i = 1; i <= 1000; i++) {sum += i;}synchronized (result.lock) {result.sum = sum;result.lock.notify();}}};t.start();synchronized (result.lock) {while (result.sum == 0) {result.lock.wait();}System.out.println(result.sum);}}
}

可以看到,上述代碼需要?個(gè)輔助類 Result,還需要使??系列的加鎖和 wait notify 操作,代碼復(fù)雜,容易出錯(cuò)。

使用Callable版本

  • 創(chuàng)建?個(gè)匿名內(nèi)部類,實(shí)現(xiàn) Callable 接?。 Callable 帶有泛型參數(shù),泛型參數(shù)表?返回值的類型。
  • 重寫(xiě) Callable 的 call ?法,完成累加的過(guò)程,直接通過(guò)返回值返回計(jì)算結(jié)果.
  • 把 callable 實(shí)例使? FutureTask 包裝?下。
  • 線程的構(gòu)造?法傳? FutureTask。 此時(shí)新線程就會(huì)執(zhí)行 FutureTask 內(nèi)部的 Callable 的 call 方法完成計(jì)算,計(jì)算結(jié)果就放到了 FutureTask 對(duì)象中。
  • 在主線程中調(diào)? futureTask.get() 能夠阻塞等待新線程計(jì)算完畢. 并獲取到 FutureTask 中的結(jié)果。
public class Demo18 {public static void main(String[] args) throws InterruptedException, ExecutionException {Callable<Integer> callable = new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 1; i <= 1000; i++) {sum += i;}return sum;}};FutureTask<Integer> futureTask = new FutureTask<>(callable);Thread t = new Thread(futureTask);t.start();int result = futureTask.get();System.out.println(result);}
}

可以看到,使? Callable 和 FutureTask 之后,代碼簡(jiǎn)化了很多,也不必?動(dòng)寫(xiě)線程同步代碼了。

相關(guān)面試題

請(qǐng)你說(shuō)說(shuō)Callable 和 Runnable 的主要區(qū)別?

考點(diǎn)5、多線程下的數(shù)據(jù)結(jié)構(gòu)

一、多線程環(huán)境使用ArrayList

  • 普通的 ArrayList 線程并不安全,在使用時(shí)必須在可能發(fā)生沖突的地方加鎖,操作復(fù)雜且容易發(fā)生死鎖。
  • 使用較多)使用Collections.synchronizedList(new ArrayList),synchronizedList 是標(biāo)準(zhǔn)庫(kù)提供的?個(gè)基于 synchronized 進(jìn)行線程同步的方法,它是 Collections 類的一個(gè)靜態(tài)方法,它的返回值是一個(gè)對(duì)關(guān)鍵方法加了鎖的鏈表(List)。這樣可以簡(jiǎn)化程序猿對(duì)代碼的加鎖操作,降低死鎖的風(fēng)險(xiǎn)。
  • ???/strong>)使? CopyOnWriteArrayList,這是一個(gè)寫(xiě)時(shí)復(fù)制的容器。
    • 原理:

      • 當(dāng)我們往?個(gè)容器添加元素的時(shí)候,不直接往當(dāng)前容器添加,而是先將當(dāng)前容器進(jìn)行Copy,復(fù)制出?個(gè)新的容器,然后新的容器里添加元素
      • 添加完元素之后,再將原容器的引用指向新的容器
    • 優(yōu)點(diǎn)

      線程可以對(duì)CopyOnWrite原容器進(jìn)行并發(fā)的讀,而不需要加鎖,因?yàn)樵萜鞑粫?huì)添加任何元素,讀和寫(xiě)是不同的容器。在讀多寫(xiě)少的場(chǎng)景下,性能很高,不需要加鎖競(jìng)爭(zhēng)。

    • 缺點(diǎn)

      占用內(nèi)存較多且新寫(xiě)的數(shù)據(jù)不能被第?時(shí)間讀取到。

二、多線程環(huán)境下使用哈希表

HashMap 本身是線程不安全的,Java 又在 HashMap 的基礎(chǔ)上封裝了兩個(gè)類:

  • Hashtable
  • ConcurrentHashMap

1、Hashtable

Hashtable 只是在 HashMap 的基礎(chǔ)上,把關(guān)鍵方法加上了鎖(synchronized),如:

public synchronized V get(Object key)
public synchronized V put(K key, V value)

這無(wú)疑是給所有讀寫(xiě)操作都加上了鎖,線程想要訪問(wèn)同一個(gè) Hashtable 的任何數(shù)據(jù)都會(huì)直接造成鎖競(jìng)爭(zhēng)(一把鎖鎖上整個(gè)Hash表,如圖,一個(gè)每次只能有一個(gè)線程訪問(wèn)該表),一旦觸發(fā)擴(kuò)容,就只有在單個(gè)線程(觸發(fā)擴(kuò)容的線程)上進(jìn)行,涉及大量的數(shù)據(jù)拷貝,效率非常低。
在這里插入圖片描述

2、ConcurrentHashMap(重點(diǎn))

ConcurrentHashMap 是 Java 并發(fā)包 java.util.concurrent 中的一個(gè)非常重要的類,用于在并發(fā)環(huán)境下替代傳統(tǒng)的 HashMap。它提供了比 Hashtable 更高的并發(fā)級(jí)別,因?yàn)?Hashtable 是同步的,這意味著在每一次訪問(wèn)時(shí),整個(gè)表都需要被鎖定,這大大降低了并發(fā)性能。ConcurrentHashMap 通過(guò)以下幾個(gè)方面的優(yōu)化和改進(jìn)來(lái)提升并發(fā)性能:

  1. 分段鎖(Segmentation Locking)(在 Java 8 之前):

    • 在 Java 8 之前,ConcurrentHashMap 使用分段鎖的機(jī)制來(lái)減少鎖的競(jìng)爭(zhēng)。它將整個(gè)哈希表分為多個(gè)段(Segment),每個(gè)段都維護(hù)著自己的鎖。這樣,在并發(fā)環(huán)境中,只要多個(gè)線程訪問(wèn)的是不同的段,它們就可以并行地執(zhí)行,從而減少了鎖的爭(zhēng)用。每個(gè)段內(nèi)部都維護(hù)了一個(gè)哈希表,用于存儲(chǔ)鍵值對(duì)。
    • 當(dāng)需要對(duì)某個(gè)鍵進(jìn)行操作時(shí),首先通過(guò)哈希碼確定該鍵屬于哪個(gè)段,然后只鎖定該段進(jìn)行操作,而不是鎖定整個(gè)表。
  2. 鎖粒度細(xì)化(Fine-grained Locking)(在 Java 8 及以后):

    • 從 Java 8 開(kāi)始,ConcurrentHashMap 放棄了分段鎖的設(shè)計(jì),轉(zhuǎn)而采用了一種更為靈活的鎖策略,即使用 Node 數(shù)組加上鏈表或紅黑樹(shù)(在鏈表過(guò)長(zhǎng)時(shí))的方式來(lái)存儲(chǔ)鍵值對(duì),并通過(guò) synchronized 關(guān)鍵字或 CAS(Compare-And-Swap)操作來(lái)確保線程安全。
    • 在 Java 8 的實(shí)現(xiàn)中,鎖被細(xì)化到了每個(gè)桶(bucket)上,即每個(gè)數(shù)組元素。當(dāng)多個(gè)線程訪問(wèn)不同的桶時(shí),它們可以并行地執(zhí)行。這進(jìn)一步減少了鎖的競(jìng)爭(zhēng),提高了并發(fā)性能。
    • 讀操作沒(méi)有加鎖(但是使用了 volatile 保證從內(nèi)存讀取結(jié)果),只對(duì)寫(xiě)操作進(jìn)行加鎖。
      在這里插入圖片描述
  3. 使用 CAS(Compare-And-Swap)操作:

    • CAS 是一種無(wú)鎖算法,用于實(shí)現(xiàn)線程間的同步,而不需要使用傳統(tǒng)的鎖。在 ConcurrentHashMap 的實(shí)現(xiàn)中,當(dāng)嘗試修改某個(gè)桶(或節(jié)點(diǎn))時(shí),會(huì)嘗試使用 CAS 操作來(lái)更新該桶的狀態(tài)。如果桶的狀態(tài)在此期間沒(méi)有被其他線程修改,則 CAS 操作成功,否則重試(CAS與版本號(hào)結(jié)合)。
    • CAS 操作減少了鎖的使用,從而提高了性能,但也可能導(dǎo)致更高的 CPU 使用率,因?yàn)樾枰粩嘀卦囍钡匠晒橹?/strong>。
  4. 動(dòng)態(tài)擴(kuò)容:

    • 定義
      ConcurrentHashMap 支持動(dòng)態(tài)擴(kuò)容,即當(dāng)哈希表中的元素?cái)?shù)量達(dá)到某個(gè)閾值時(shí),會(huì)自動(dòng)進(jìn)行擴(kuò)容操作,以避免哈希沖突和性能下降。與 HashMap 類似,擴(kuò)容操作涉及到重新計(jì)算每個(gè)元素的哈希碼,并將其放置到新的哈希表中。但 ConcurrentHashMap 的擴(kuò)容操作是并發(fā)安全的可以在不阻塞讀操作的情況下進(jìn)行。
    • 原理
      • 發(fā)現(xiàn)需要擴(kuò)容的線程,只需要?jiǎng)?chuàng)建?個(gè)新的數(shù)組,同時(shí)只搬幾個(gè)元素過(guò)去。
      • 擴(kuò)容期間, 新老數(shù)組同時(shí)存在,后續(xù)每個(gè)來(lái)操作 ConcurrentHashMap 的線程,都會(huì)參與搬家的過(guò)程,每個(gè)操作負(fù)責(zé)搬運(yùn)一小部分元素,搬完最后?個(gè)元素再把老數(shù)組刪掉。
      • 這個(gè)期間,插入的元素只往新數(shù)組里添加,查找需要同時(shí)查新數(shù)組和?數(shù)組。
  5. 紅黑樹(shù)優(yōu)化:

    • 在 Java 8 及以后的版本中,當(dāng)某個(gè)桶中的鏈表長(zhǎng)度超過(guò)一定閾值時(shí)(默認(rèn)為 8),ConcurrentHashMap 會(huì)將該鏈表轉(zhuǎn)換為紅黑樹(shù),以優(yōu)化查找性能。這是因?yàn)榧t黑樹(shù)在查找、插入和刪除操作上的時(shí)間復(fù)雜度比鏈表更低(在平均和最壞情況下都是 O(log n)),可以進(jìn)一步提高并發(fā)性能。

綜上所述,ConcurrentHashMap 通過(guò)分段鎖(在 Java 8 之前)、鎖粒度細(xì)化(在 Java 8 及以后)、CAS 操作、動(dòng)態(tài)擴(kuò)容和紅黑樹(shù)優(yōu)化等多種機(jī)制來(lái)優(yōu)化和改進(jìn)并發(fā)性能,使其成為 Java 中處理并發(fā)哈希表的首選數(shù)據(jù)結(jié)構(gòu)。

相關(guān)面試題

  1. ConcurrentHashMap的讀是否要加鎖,為什么?
  2. 介紹下 ConcurrentHashMap的鎖分段技術(shù)?
  3. ConcurrentHashMap在jdk1.8做了哪些優(yōu)化?
  4. Hashtable和HashMap、ConcurrentHashMap 之間的區(qū)別?

考點(diǎn)五、其他常見(jiàn)面試題

以下的面試題的答案都在我之前的文章中,大家可以從中尋找答案,這里我就不再一一贅述。

  1. 談?wù)?volatile關(guān)鍵字的用法?

    參考文章 線程安全

  2. Java多線程是如何實(shí)現(xiàn)數(shù)據(jù)共享的?

    JVM 把內(nèi)存分成了這幾個(gè)區(qū)域; ?法區(qū), 堆區(qū), 棧區(qū), 程序計(jì)數(shù)器。 其中堆區(qū)這個(gè)內(nèi)存區(qū)域是多個(gè)線程之間共享的。只要把某個(gè)數(shù)據(jù)放到堆內(nèi)存中,就可以讓多個(gè)線程都能訪問(wèn)到。

  3. Java創(chuàng)建線程池的接?是什么?參數(shù) LinkedBlockingQueue 的作用是什么?

    參考文章 線程池的認(rèn)識(shí)和使用

  4. Java線程共有幾種狀態(tài)?狀態(tài)之間怎么切換的?

    參考文章
    線程安全
    Thread類和線程的用法

  5. Thread和Runnable的區(qū)別和聯(lián)系?

    參考文章 Thread類和線程的用法

http://www.risenshineclean.com/news/54528.html

相關(guān)文章:

  • 投票網(wǎng)站開(kāi)發(fā)的背景和意義免費(fèi)網(wǎng)站seo排名優(yōu)化
  • 用淘寶域名做網(wǎng)站什么效果百度口碑網(wǎng)
  • 北京工商注冊(cè)代理記賬最新黑帽seo培訓(xùn)
  • 公司網(wǎng)站在國(guó)外打開(kāi)很慢使用cdn好還是國(guó)外租用服務(wù)器好互聯(lián)網(wǎng)營(yíng)銷推廣公司
  • 電商網(wǎng)站的建設(shè)與維護(hù)域名查詢網(wǎng)址
  • 最新百度快速收錄技術(shù)seo軟件定制
  • 淘寶上做網(wǎng)站的信得過(guò)嗎手機(jī)系統(tǒng)優(yōu)化軟件
  • 國(guó)外網(wǎng)站推廣百度查詢
  • 如何制作網(wǎng)站的app海會(huì)網(wǎng)絡(luò)做的網(wǎng)站怎么做優(yōu)化
  • 免費(fèi)網(wǎng)頁(yè)設(shè)計(jì)作業(yè)文件seo屬于什么職業(yè)部門(mén)
  • 優(yōu)化方案物理電子版百度信息流優(yōu)化
  • 普通網(wǎng)站要什么費(fèi)用推廣軟文300字范文
  • wordpress 評(píng)論倒敘seo搜索引擎優(yōu)化薪資
  • 自己做一個(gè)網(wǎng)站難么新手做seo怎么做
  • 網(wǎng)站建設(shè)實(shí)例教程 pdf中國(guó)品牌策劃公司排名
  • 黃山做網(wǎng)站公司鄭州免費(fèi)做網(wǎng)站
  • 網(wǎng)站百度地圖導(dǎo)航代碼生成網(wǎng)店運(yùn)營(yíng)工資一般多少
  • 外網(wǎng)視頻網(wǎng)站做泥聲控百度seo權(quán)重
  • 湖北平臺(tái)網(wǎng)站建設(shè)制作南京seo排名收費(fèi)
  • 郵箱地址怎么注冊(cè)seo優(yōu)化seo外包
  • 電子商務(wù)網(wǎng)站制作重慶seo整站優(yōu)化設(shè)置
  • 做網(wǎng)站都有哪些費(fèi)用抖音推廣方案
  • 濟(jì)寧住房和城鄉(xiāng)建設(shè)廳網(wǎng)站首頁(yè)關(guān)鍵詞查詢工具有哪些
  • ip地址獲取揭陽(yáng)市seo上詞外包
  • 企業(yè)做網(wǎng)站維護(hù)自己建網(wǎng)站怎么推廣
  • 工程造價(jià)專業(yè)建設(shè)規(guī)劃西安網(wǎng)站seo排名優(yōu)化
  • 百度搜索引擎錄入網(wǎng)站整站優(yōu)化 mail
  • 課程微網(wǎng)站開(kāi)發(fā)技術(shù)昆明seo優(yōu)化
  • 手機(jī)建造網(wǎng)站2022適合小學(xué)生的簡(jiǎn)短新聞
  • 怎么在百度首頁(yè)做網(wǎng)站百度的特點(diǎn)和優(yōu)勢(shì)