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

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

做社群的網(wǎng)站有哪些西安百度推廣怎么做

做社群的網(wǎng)站有哪些,西安百度推廣怎么做,大氣的企業(yè)網(wǎng)站模板,嘉善網(wǎng)站設(shè)計(jì)你好,我是 shengjk1,多年大廠經(jīng)驗(yàn),努力構(gòu)建 通俗易懂的、好玩的編程語言教程。 歡迎關(guān)注!你會(huì)有如下收益: 了解大廠經(jīng)驗(yàn)擁有和大廠相匹配的技術(shù)等 希望看什么,評(píng)論或者私信告訴我! 文章目錄 一…

你好,我是 shengjk1,多年大廠經(jīng)驗(yàn),努力構(gòu)建 通俗易懂的、好玩的編程語言教程。 歡迎關(guān)注!你會(huì)有如下收益:

  1. 了解大廠經(jīng)驗(yàn)
  2. 擁有和大廠相匹配的技術(shù)等

希望看什么,評(píng)論或者私信告訴我!

文章目錄

  • 一、背景
  • 二、線程之間通信的基本儲(chǔ)備
    • 2.1 為什么線程之間需要通信
    • 2.2 現(xiàn)代處理器結(jié)構(gòu)
    • 2.3 基于現(xiàn)代處理器結(jié)構(gòu)下的線程運(yùn)行模型
    • 2.4 線程工作內(nèi)存帶來的問題
  • 三、volatile 和 synchronized
    • 3.1 volatile是什么
      • 3.1.1 可見性
      • 3.1.2 禁止指令重排序優(yōu)化
      • 3.1.3 內(nèi)存屏障(Memory Barrier)
      • 3.1.4 不保證原子性
      • 3.1.5 使用場(chǎng)景
    • 3.2 volatile 原理和例子
    • 3.2 synchronized 是什么
      • 3.2.1. 基本用法
        • 3.2.1.1 同步方法
        • 3.2.1.2 同步代碼塊
      • 3.2.2. 工作原理
      • 3.2.3. 保證原子性和可見性
    • 3.3 synchronized 原理和例子
  • 四、總結(jié)


一、背景

前面兩篇,我們分別知道了 關(guān)于 java 多線程,你需要知道的一些基礎(chǔ)知識(shí) 以及 關(guān)于 java 多線程,你需要知道的一些基礎(chǔ)知識(shí)
本篇文章呢,我們繼續(xù)死磕 java 多線程,來聊一聊 java 多線程之間是如何通信的-volatile 和 synchronized

二、線程之間通信的基本儲(chǔ)備

2.1 為什么線程之間需要通信

在線程編程中,線程之間需要相互通信的主要原因是協(xié)作和數(shù)據(jù)共享。以下是一些主要的原因:

  1. 資源共享: 多個(gè)線程可能需要同時(shí)訪問和操作共享的資源,如數(shù)據(jù)結(jié)構(gòu)、文件、網(wǎng)絡(luò)連接等。為了避免數(shù)據(jù)競(jìng)爭(zhēng)和確保數(shù)據(jù)的一致性,線程之間需要通信來協(xié)調(diào)對(duì)共享資源的訪問。

  2. 任務(wù)分工: 在多線程編程中,不同線程可以負(fù)責(zé)不同的任務(wù)或子任務(wù),線程之間需要協(xié)作和通信以完成整體的工作。通信可以是單向的傳達(dá)結(jié)果,也可以是雙向的交換信息和狀態(tài)。

  3. 同步操作: 線程之間的通信可以用于同步操作,例如一個(gè)線程需要等待另一個(gè)線程完成某個(gè)任務(wù)后才能繼續(xù)執(zhí)行,或者通知其他線程某個(gè)事件已發(fā)生。

  4. 數(shù)據(jù)傳遞: 線程之間通過通信來傳遞數(shù)據(jù)和消息,以便于協(xié)調(diào)工作、共享信息或通知事件。

  5. 提高性能: 在某些情況下,通過線程之間的通信和協(xié)作可以提高程序的性能,例如使用線程池執(zhí)行并發(fā)任務(wù)時(shí),可以減少線程的創(chuàng)建和銷毀開銷。

  6. 實(shí)現(xiàn)某些模型和算法: 有些并發(fā)模型和算法需要線程之間的協(xié)作和通信,如生產(chǎn)者消費(fèi)者模型、并發(fā)隊(duì)列等。

綜上所述,線程之間的通信在多線程編程中是非常重要的,能夠?qū)崿F(xiàn)不同線程之間的協(xié)作、數(shù)據(jù)共享、任務(wù)分工等功能,從而有效利用計(jì)算資源并實(shí)現(xiàn)復(fù)雜的并發(fā)任務(wù)。

2.2 現(xiàn)代處理器結(jié)構(gòu)

一般情況下,現(xiàn)代處理器通常會(huì)包含一級(jí)緩存(L1 Cache)、二級(jí)緩存(L2 Cache)、和三級(jí)緩存(L3 Cache)。這些緩存一般都是集成在處理器芯片內(nèi)部的,被稱為“內(nèi)置緩存”(On-Chip Cache),用于加快數(shù)據(jù)的訪問速度和減少對(duì)主內(nèi)存的訪問。這里有一個(gè) 2020年的數(shù)據(jù)

L1 cache 訪問時(shí)間是 1ns
L2 cache 訪問時(shí)間是 4ns
主存訪問時(shí)間是 100ns

具體關(guān)于三級(jí)緩存(L3 Cache)通常的情況包括:

  1. 位置: L3 Cache通常位于處理器芯片內(nèi)部,但是相對(duì)于L1和L2 Cache,它的容量更大,從幾MB到幾十MB不等。
  2. 作用: L3 Cache主要用來緩存多個(gè)核心之間共享的數(shù)據(jù),以提高處理器核心之間的數(shù)據(jù)共享效率。
  3. 互相之間是否獨(dú)立: 不同處理器核心之間可以訪問共享的L3 Cache,這有助于提高多個(gè)核心之間數(shù)據(jù)訪問的效率。

由于L3 Cache容量較大且能夠?yàn)槎鄠€(gè)核心提供共享數(shù)據(jù)緩存,因此它可以有效地提高多核處理器系統(tǒng)中核心之間的數(shù)據(jù)共享和協(xié)作效率。雖然L3 Cache通常也集成在處理器芯片內(nèi)部,但某些處理器架構(gòu)可能會(huì)將部分L3 Cache放置在處理器芯片外部以適應(yīng)不同的需求。
在這里插入圖片描述
當(dāng)系統(tǒng)運(yùn)行時(shí),CPU執(zhí)行計(jì)算的過程如下:

  1. 程序以及數(shù)據(jù)被加載到主內(nèi)存
  2. 指令和數(shù)據(jù)被加載到CPU緩存
  3. CPU執(zhí)行指令,把結(jié)果寫到高速緩存
  4. 高速緩存中的數(shù)據(jù)寫回主內(nèi)存

2.3 基于現(xiàn)代處理器結(jié)構(gòu)下的線程運(yùn)行模型

在這里插入圖片描述

線程的工作內(nèi)存其實(shí)就是多級(jí)緩存以及CPU寄存器的抽象。

所以每個(gè)線程在運(yùn)行時(shí)確實(shí)都會(huì)有自己的一套完整的上下文,這個(gè)上下文包含了線程當(dāng)前的狀態(tài)、執(zhí)行環(huán)境以及必要的數(shù)據(jù)。這個(gè)上下文在線程切換時(shí)被保存和恢復(fù),以確保線程可以從中斷點(diǎn)繼續(xù)執(zhí)行。下面是上下文的一些重要組成部分:

  1. 寄存器狀態(tài): 在上下文中,包含了線程當(dāng)前寄存器的狀態(tài)。寄存器存儲(chǔ)了當(dāng)前線程的執(zhí)行環(huán)境,包括程序計(jì)數(shù)器、棧指針、各種通用寄存器等。

  2. 棧: 程序使用的棧包含了函數(shù)調(diào)用、局部變量以及其他執(zhí)行環(huán)境的信息。每個(gè)線程都有自己的棧,用于存儲(chǔ)執(zhí)行過程中的臨時(shí)數(shù)據(jù)。

  3. 程序計(jì)數(shù)器(Program Counter): 程序計(jì)數(shù)器存儲(chǔ)著當(dāng)前執(zhí)行的指令地址或者是下一條待執(zhí)行的指令地址。

  4. 線程狀態(tài): 這部分描述了線程當(dāng)前所處的狀態(tài),比如運(yùn)行態(tài)、就緒態(tài)、阻塞態(tài)等。線程狀態(tài)的改變會(huì)觸發(fā)線程調(diào)度。

  5. 權(quán)限和訪問控制: 上下文中可能包含了線程的權(quán)限信息,以確保線程的操作在合適的權(quán)限下進(jìn)行。

  6. 堆棧指針信息: 記錄了當(dāng)前線程堆棧的指針位置,在進(jìn)行棧操作時(shí)起著重要作用。

  7. 資源分配信息: 上下文還可能包括了線程已獲得的資源、線程使用的棧大小等信息。

通過保存和恢復(fù)這些上下文信息,操作系統(tǒng)能夠有效地管理多個(gè)線程的執(zhí)行,實(shí)現(xiàn)線程之間的切換和并發(fā)執(zhí)行。這些上下文信息是確保線程能夠在不同執(zhí)行環(huán)境下正確運(yùn)行的關(guān)鍵。

2.4 線程工作內(nèi)存帶來的問題

線程有自己的工作內(nèi)存最大的問題之一就是數(shù)據(jù)不一致性問題。這種情況可以導(dǎo)致程序出現(xiàn)難以預(yù)測(cè)的錯(cuò)誤行為,因?yàn)槎鄠€(gè)線程可能會(huì)在各自的工作內(nèi)存中緩存共享變量的副本,而這些副本的更新可能無法即時(shí)反映到其他線程中,引發(fā)數(shù)據(jù)的不一致性。

數(shù)據(jù)不一致性問題的一些常見情形包括:

  1. 寫問題(Write Problem): 一個(gè)線程在自己的工作內(nèi)存中修改了共享變量但未立即寫回主內(nèi)存,導(dǎo)致其他線程無法立即看到這個(gè)變化。

  2. 讀問題(Read Problem): 一個(gè)線程從主內(nèi)存中讀取了共享變量的值,但由于另一個(gè)線程已經(jīng)對(duì)該變量進(jìn)行了修改,該線程的工作內(nèi)存中的值已經(jīng)過時(shí),導(dǎo)致讀取的值不正確。

  3. 指令重排序問題: 編譯器或處理器可能會(huì)對(duì)指令進(jìn)行重排序優(yōu)化,這可能導(dǎo)致線程在不同的順序下訪問共享變量,進(jìn)而使得數(shù)據(jù)出現(xiàn)不一致的情況。

其實(shí)就是兩類問題:

  1. 數(shù)據(jù)可見性的問題,即另外一個(gè)線程改了共享變量,我能不能馬上知道。
  2. 共享變量一致性的問題,即多個(gè)線程操作同一個(gè)共享變量,它的結(jié)果能不能跟非多線程操作同一個(gè)共享變量的結(jié)果一致。

為了解決上述的兩個(gè)問題,我們引入了 volatile 和 synchronized

三、volatile 和 synchronized

3.1 volatile是什么

volatile 是 Java 中的一個(gè)關(guān)鍵字,主要用于確保多線程環(huán)境下變量的可見性和有序性。當(dāng)一個(gè)變量被聲明為 volatile 時(shí),意味著這個(gè)變量可能會(huì)被多個(gè)線程同時(shí)訪問和修改,因此需要使用 volatile 來確保所有線程都能看到變量的最新值。

下面是 volatile 的詳細(xì)解釋:

3.1.1 可見性

在多線程環(huán)境中,一個(gè)線程修改了一個(gè)共享變量的值,另一個(gè)線程無法立即看到這個(gè)變化,除非它主動(dòng)讀取該變量的值。而 volatile 關(guān)鍵字保證了當(dāng)一個(gè)線程修改了一個(gè) volatile 變量的值后,其他線程會(huì)立即看到這個(gè)變化。這是因?yàn)?volatile 變量不會(huì)被緩存到線程的工作內(nèi)存中,每次讀取 volatile 變量時(shí)都會(huì)直接從主內(nèi)存中獲取最新值。

3.1.2 禁止指令重排序優(yōu)化

編譯器和處理器可能會(huì)對(duì)代碼進(jìn)行指令重排序優(yōu)化,以提高執(zhí)行效率。但是,在某些情況下,這種重排序可能會(huì)導(dǎo)致多線程環(huán)境下的數(shù)據(jù)不一致問題。volatile 關(guān)鍵字可以防止這種情況發(fā)生,它會(huì)告訴編譯器和處理器不要對(duì)這個(gè)變量進(jìn)行重排序優(yōu)化。

3.1.3 內(nèi)存屏障(Memory Barrier)

現(xiàn)代處理器為了提高性能會(huì)對(duì)內(nèi)存操作進(jìn)行優(yōu)化,包括重新排序讀寫操作。為了強(qiáng)制處理器的操作符合程序員的預(yù)期順序,編譯器會(huì)在使用volatile的讀/寫操作周圍插入內(nèi)存屏障(Memory Barrier)。這些內(nèi)存屏障是一種同步機(jī)制,用于阻止屏障兩側(cè)的指令被重排序。通過確保特定的讀寫操作順序執(zhí)行,內(nèi)存屏障確保了程序中的某些操作在特定時(shí)刻已經(jīng)執(zhí)行完成或已經(jīng)啟動(dòng)執(zhí)行,從而在多線程環(huán)境中維持操作的有序性。

3.1.4 不保證原子性

雖然 volatile 可以保證可見性和禁止指令重排序優(yōu)化,但它不能保證復(fù)合操作(如自增或自減等)的原子性。如果需要一個(gè)變量在多線程環(huán)境下的原子性操作,如計(jì)數(shù)或狀態(tài)更新等,應(yīng)該使用 AtomicIntegerAtomicLong 等原子類或者使用 synchronized 塊來保證原子性。但對(duì)于簡(jiǎn)單的狀態(tài)標(biāo)記(例如一個(gè)標(biāo)志位),volatile 是足夠的。

3.1.5 使用場(chǎng)景

volatile 主要用于以下場(chǎng)景:

  1. 狀態(tài)標(biāo)記:例如用于標(biāo)記某個(gè)任務(wù)是否已經(jīng)完成。在這種情況下,一個(gè)線程會(huì)檢查這個(gè)標(biāo)記,然后基于這個(gè)標(biāo)記的值來決定下一步行動(dòng)。如果這個(gè)標(biāo)記在多線程環(huán)境下被使用,并且可能被多個(gè)線程同時(shí)修改,那么就需要使用 volatile 來確保每個(gè)線程都能看到最新的標(biāo)記值。
  2. 單例模式的雙重檢查鎖定:在某些單例模式的實(shí)現(xiàn)中,會(huì)使用 volatile 來確保實(shí)例在多個(gè)線程間的正確創(chuàng)建和訪問。

總的來說,volatile 是一個(gè)輕量級(jí)的同步機(jī)制,用于確保多線程環(huán)境下變量的可見性和有序性。但在需要復(fù)雜同步操作或原子性保證的情況下,可能需要考慮使用更強(qiáng)大的同步機(jī)制,如 synchronized 塊或鎖。

3.2 volatile 原理和例子

volatile 狀態(tài)標(biāo)記 的例子:

public class StopThreadExample {// 使用volatile修飾的變量來確保所有線程都能看到最新的標(biāo)志位值private volatile boolean flag= true;// 一個(gè)任務(wù)執(zhí)行線程,它持續(xù)檢查標(biāo)志位并根據(jù)標(biāo)志位決定是否繼續(xù)運(yùn)行public void runTask() {while (isRunning) { // 使用volatile修飾的變量確保我們能正確讀取到最新的狀態(tài)// 這里模擬一些耗時(shí)任務(wù)System.out.println("執(zhí)行任務(wù)...");try {Thread.sleep(1000); // 模擬耗時(shí)操作,這里暫停一秒} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("任務(wù)執(zhí)行線程已經(jīng)停止.");}public static void main(String[] args) throws InterruptedException {StopThreadExample example = new StopThreadExample();Thread taskThread = new Thread(() -> example.runTask()); // 啟動(dòng)任務(wù)執(zhí)行線程taskThread.start(); // 開始執(zhí)行任務(wù)線程try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}; // 讓主線程暫停幾秒以便觀察效果,模擬主線程正在做其他事情的情況System.out.println("停止任務(wù)執(zhí)行線程..."); // 在主線程中通知任務(wù)執(zhí)行線程停止執(zhí)行example.flag= false; // 設(shè)置標(biāo)志位來停止任務(wù)執(zhí)行線程,所有線程都會(huì)看到最新的標(biāo)志位值,因?yàn)槭褂昧藇olatile關(guān)鍵字修飾isRunning變量taskThread.join(); // 確保任務(wù)執(zhí)行線程停止后主線程繼續(xù)執(zhí)行接下來的代碼或結(jié)束程序(這一步依賴于主線程的下一步動(dòng)作)System.out.println("主線程結(jié)束."); // 當(dāng)任務(wù)執(zhí)行線程已經(jīng)停止后,主線程結(jié)束程序或繼續(xù)其他操作(這里模擬主線程的下一步動(dòng)作)}
}

在字節(jié)碼層面 volatile 原理,是通過 flags 表示來實(shí)現(xiàn)的
在這里插入圖片描述

3.2 synchronized 是什么

synchronized 是 Java 中用于控制多線程并發(fā)訪問共享資源的一種關(guān)鍵字。它可以確保多個(gè)線程在同一時(shí)刻只能有一個(gè)線程執(zhí)行某個(gè)代碼塊或方法,從而避免并發(fā)問題,如競(jìng)態(tài)條件。以下是關(guān)于 synchronized 的詳細(xì)介紹:

3.2.1. 基本用法

3.2.1.1 同步方法

直接在方法聲明上使用 synchronized 關(guān)鍵字,這樣整個(gè)方法都在同步塊內(nèi)。例如:

public synchronized void synchronizedMethod() {// 同步代碼塊
}

此時(shí),該方法只能由一個(gè)線程在任何時(shí)候訪問。多個(gè)線程調(diào)用此方法時(shí),其他線程會(huì)被阻塞直到當(dāng)前線程執(zhí)行完畢。這種方法的同步鎖是當(dāng)前實(shí)例對(duì)象(即 this)。如果要同步的是靜態(tài)方法,鎖是類的 Class 對(duì)象。

3.2.1.2 同步代碼塊

可以使用 synchronized(鎖對(duì)象) 語法創(chuàng)建一個(gè)同步代碼塊。例如:

synchronized (lockObject) {// 同步代碼塊內(nèi)容
}

此時(shí),只有持有鎖對(duì)象的線程可以進(jìn)入該代碼塊。多個(gè)線程可以嘗試訪問這個(gè)同步塊,但只有一個(gè)能獲得鎖并執(zhí)行其中的代碼。其他線程會(huì)被阻塞直到鎖被釋放。鎖對(duì)象可以是任何對(duì)象,通常是一個(gè)自然存在的共享資源或者一個(gè)特定的鎖對(duì)象。當(dāng)鎖對(duì)象是 this 時(shí),相當(dāng)于同步整個(gè)方法。如果鎖對(duì)象是某個(gè)靜態(tài)變量,那么任何線程調(diào)用這段代碼都需要獲得那個(gè)鎖才能執(zhí)行。但一定要確保使用的鎖對(duì)象不會(huì)在方法中頻繁變化。如果對(duì)象在不同的上下文中表示不同的資源或意義,則可能導(dǎo)致意外的并發(fā)問題。

3.2.2. 工作原理

當(dāng)一個(gè)線程進(jìn)入一個(gè) synchronized 代碼塊或方法時(shí),它首先嘗試獲取鎖對(duì)象對(duì)應(yīng)的內(nèi)置鎖(也稱為監(jiān)視器鎖)。如果鎖已經(jīng)被另一個(gè)線程持有,那么該線程將會(huì)進(jìn)入等待狀態(tài),直到鎖被釋放(由持有鎖的線程退出同步塊或調(diào)用 wait() 方法)。這種機(jī)制確保了同一時(shí)刻只有一個(gè)線程可以訪問同步代碼塊或方法中的共享資源。一旦線程釋放鎖(退出同步塊或方法),其他等待的線程將有機(jī)會(huì)嘗試獲取該鎖并執(zhí)行相應(yīng)的代碼。如果多個(gè)線程同時(shí)嘗試獲取同一個(gè)對(duì)象的鎖,它們會(huì)被按照某種順序來串行化地執(zhí)行同步代碼塊或方法。值得注意的是,同步控制開銷通常比上下文切換的開銷要小得多。此外,JVM 會(huì)嘗試優(yōu)化鎖的獲取和釋放過程以提高性能。對(duì)于復(fù)雜的應(yīng)用場(chǎng)景,還有專門的性能調(diào)優(yōu)和死鎖避免策略可用。

3.2.3. 保證原子性和可見性

是的,我的解釋是正確的。在 Java 中使用 synchronized 關(guān)鍵字時(shí),確實(shí)涉及到內(nèi)存模型和工作內(nèi)存與主內(nèi)存的刷新問題,特別是在多線程環(huán)境下。讓我們?cè)俅卧敿?xì)解釋這一點(diǎn)。

當(dāng)你在 Java 程序中使用 synchronized 塊時(shí),這個(gè)關(guān)鍵字確保了多個(gè)線程對(duì)共享資源的同步訪問。這是通過確保只有一個(gè)線程能夠獲取到鎖來實(shí)現(xiàn)的。在這個(gè)同步塊內(nèi),所有的讀寫操作都是對(duì)該鎖對(duì)象的原子操作。這就意味著當(dāng)一個(gè)線程進(jìn)入 synchronized 塊時(shí),它會(huì)獲取鎖對(duì)象,并開始執(zhí)行同步塊內(nèi)的代碼。此時(shí),其他嘗試進(jìn)入該同步塊的線程會(huì)被阻塞,直到持有鎖的線程釋放鎖為止。

在這個(gè)過程中,涉及到內(nèi)存模型和工作內(nèi)存與主內(nèi)存的交互:

  • 互斥訪問:當(dāng)一個(gè)線程進(jìn)入 synchronized 塊時(shí),它需要獲得鎖。只有獲得鎖的線程才能執(zhí)行同步塊內(nèi)的代碼,從而保證了同一時(shí)刻只有一個(gè)線程在操作共享變量。
  • 工作內(nèi)存與主內(nèi)存的刷新:當(dāng)一個(gè)線程持有鎖并執(zhí)行同步塊內(nèi)的操作時(shí),它會(huì)首先從主內(nèi)存中讀取共享資源到工作內(nèi)存中(即線程的本地緩存)。在工作內(nèi)存中修改這些數(shù)據(jù)后,只有當(dāng)線程釋放鎖并允許其他線程獲取鎖時(shí),這些修改才會(huì)被寫回主內(nèi)存。這就意味著同步塊內(nèi)的操作保證了在工作內(nèi)存中對(duì)共享數(shù)據(jù)的操作在所有線程之間是一致的。
  • 緩存一致性:在多線程環(huán)境中,緩存一致性是確保多個(gè)線程之間共享的數(shù)據(jù)保持一致性的過程。synchronized 塊確保了在任何時(shí)候只有一個(gè)線程能夠修改共享數(shù)據(jù),從而避免了緩存不一致的問題。即使其他線程嘗試讀取或?qū)懭牍蚕頂?shù)據(jù),由于它們被阻塞在鎖之外,它們不能看到在工作內(nèi)存中的修改,除非持有鎖的線程釋放鎖并允許它們獲取鎖。

簡(jiǎn)而言之,synchronized 通過確保對(duì)共享資源的獨(dú)占訪問來強(qiáng)制工作內(nèi)存與主內(nèi)存的刷新,從而保證了緩存一致性。它確保了任何線程在訪問或修改共享數(shù)據(jù)時(shí)都是實(shí)時(shí)的并且一致的。

3.3 synchronized 原理和例子

public class Counter {private int count = 0; // 共享資源:計(jì)數(shù)器// synchronized 塊用于保護(hù)對(duì) count 的并發(fā)訪問public synchronized void increment() {count++; // 對(duì)共享資源的操作(這里是增加計(jì)數(shù)器的值)}public int getCount() {return count; // 外部訪問共享資源(可能需要同步)}public static void main(String[] args) throws InterruptedException {Counter counter = new Counter(); // 創(chuàng)建 Counter 實(shí)例對(duì)象// 創(chuàng)建多個(gè)線程,模擬并發(fā)增加計(jì)數(shù)器的值for (int i = 0; i < 10; i++) { // 創(chuàng)建 10 個(gè)線程來并發(fā)增加計(jì)數(shù)器的值Thread thread = new Thread(() -> {for (int j = 0; j < 100; j++) { // 每個(gè)線程都嘗試增加計(jì)數(shù)器值多次以模擬并發(fā)情況counter.increment(); // 使用 synchronized 塊來安全地增加計(jì)數(shù)器值}});thread.start(); // 啟動(dòng)線程thread.join();} // 循環(huán)結(jié)束后,所有線程都已經(jīng)啟動(dòng)并嘗試增加計(jì)數(shù)器的值。由于使用了 synchronized 塊,計(jì)數(shù)器的值將準(zhǔn)確累積而不會(huì)發(fā)生沖突或重疊增加的情況。可以檢查 getCount() 的返回值來驗(yàn)證這一點(diǎn)。System.out.println(counter.count);}
}

在字節(jié)碼層面 synchronized 原理

  1. 方法同步: 對(duì)于使用synchronized修飾的方法,JVM會(huì)在方法的訪問修飾符字節(jié)碼指令之前插入一個(gè)特殊的指令,稱為“ACC_SYNCHRONIZED”。這個(gè)標(biāo)志告訴JVM該方法需要一個(gè)鎖來執(zhí)行。當(dāng)線程調(diào)用這個(gè)方法時(shí),它必須先獲得對(duì)象的內(nèi)置鎖(即實(shí)例鎖)。持有鎖的線程可以在該對(duì)象的任何方法上執(zhí)行任何操作,而不會(huì)阻塞其他線程對(duì)同一個(gè)對(duì)象的訪問。當(dāng)方法返回時(shí),鎖會(huì)被自動(dòng)釋放。

  2. 代碼塊同步: 對(duì)于使用synchronized(obj)修飾的代碼塊,Java編譯器會(huì)在該代碼塊的起始和結(jié)束位置生成特定的字節(jié)碼指令。具體來說,它會(huì)使用monitorentermonitorexit指令。monitorenter指令用于獲取對(duì)象的內(nèi)部鎖,而monitorexit指令用于釋放該鎖。這兩個(gè)指令確保了同步代碼塊中的代碼是原子的,并且不會(huì)被其他嘗試獲取同一鎖的線程中斷。如果在持有鎖的過程中發(fā)生了異常,需要確保monitorexit指令始終被執(zhí)行以釋放鎖。

四、總結(jié)

在多線程編程中,線程之間的通信非常重要,它可以實(shí)現(xiàn)資源共享、任務(wù)分工、同步操作、數(shù)據(jù)傳遞和提高性能等功能。為了確保線程之間的通信的正確性和效率,可以使用volatile關(guān)鍵字和synchronized關(guān)鍵字。volatile關(guān)鍵字可以保證可見性和禁止指令重排序優(yōu)化,而synchronized關(guān)鍵字可以保證對(duì)共享資源的同步訪問,保證原子性和可見性。

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

相關(guān)文章:

  • wordpress html插件優(yōu)化網(wǎng)站做什么的
  • 哪家公司做網(wǎng)站最好網(wǎng)絡(luò)營銷專業(yè)技能
  • 明年做那些網(wǎng)站致富網(wǎng)站優(yōu)化包括哪些
  • 無極網(wǎng)站站怎么有的下不了如何讓百度收錄自己信息
  • 新都網(wǎng)站開發(fā)鄭州百度網(wǎng)站優(yōu)化排名
  • 營銷網(wǎng)站的搭建磁力兔子
  • 類似非小號(hào)的網(wǎng)站怎么做軟文推廣一般發(fā)布在哪些平臺(tái)
  • 上城網(wǎng)站建設(shè)百度快照推廣是什么意思
  • 網(wǎng)站添加視頻代碼網(wǎng)絡(luò)建站流程
  • 亞馬遜做deal的網(wǎng)站淘寶指數(shù)網(wǎng)址
  • 網(wǎng)站建設(shè)怎樣上傳程序企業(yè)網(wǎng)站營銷的實(shí)現(xiàn)方式
  • 做網(wǎng)站的畢設(shè)開題依據(jù)在線注冊(cè)網(wǎng)站
  • 如何在office做網(wǎng)站360站長平臺(tái)
  • 公司網(wǎng)站維護(hù)好做嗎百度移動(dòng)端排名軟件
  • 網(wǎng)站建設(shè)外包流程網(wǎng)站排名優(yōu)化怎樣做
  • 萊蕪亓家網(wǎng)站優(yōu)化神馬網(wǎng)站關(guān)鍵詞排名價(jià)格
  • 網(wǎng)站建設(shè)在線視頻百度云搜索入口
  • diy做網(wǎng)站搜索關(guān)鍵詞的工具
  • 學(xué)做靜態(tài)網(wǎng)站怎么做電商生意
  • 織夢(mèng)網(wǎng)站聯(lián)系我們的地圖怎么做關(guān)鍵詞搜索廣告
  • 湛江模板建站系統(tǒng)海外短視頻軟件
  • 哪里做網(wǎng)站最好小時(shí)seo加盟
  • 建設(shè)云南省癌癥中心網(wǎng)站關(guān)鍵詞優(yōu)化價(jià)格
  • 網(wǎng)站新聞對(duì)百度優(yōu)化有用嗎百度網(wǎng)盤搜索入口
  • 虛擬主機(jī)怎么弄網(wǎng)站南昌seo推廣
  • 網(wǎng)站專做盜版小說 會(huì)犯法嗎百度搜索指數(shù)排行榜
  • 諸城網(wǎng)絡(luò)營銷免費(fèi)發(fā)seo外鏈平臺(tái)
  • 廈門大型企業(yè)網(wǎng)站開發(fā)公司高級(jí)seo招聘
  • 學(xué)校教育網(wǎng)站模板惡意點(diǎn)擊推廣神器
  • 有沒有好網(wǎng)站推薦提升網(wǎng)頁優(yōu)化排名