成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java 并發(fā)編程系列之帶你了解多線程

Elle / 3461人閱讀

摘要:的內(nèi)置鎖是一種互斥鎖,意味著最多只有一個線程能持有這種鎖。使用方式如下使用顯示鎖之前,解決多線程共享對象訪問的機制只有和。后面會陸續(xù)的補充并發(fā)編程系列的文章。

早期的計算機不包含操作系統(tǒng),它們從頭到尾執(zhí)行一個程序,這個程序可以訪問計算機中的所有資源。在這種情況下,每次都只能運行一個程序,對于昂貴的計算機資源來說是一種嚴重的浪費。

操作系統(tǒng)出現(xiàn)后,計算機可以運行多個程序,不同的程序在多帶帶的進程中運行。操作系統(tǒng)負責為各個獨立的進程分配各種資源。并且不同的進程間可以通過一些通信機制來交換數(shù)據(jù),比如:套接字、信號處理器、共享內(nèi)存、信號量等。

一、了解多線程

1.1 進程與線程

想必大家都聽說過這兩個名詞,它們之間有什么聯(lián)系與不同呢?

記得當時上操作系統(tǒng)課時,書上有這么一句話:進程是獨立擁有 cpu 資源的最 小單位,線程是接受 cpu 調(diào)度的最小單位。網(wǎng)上看了那么多的解釋,還是覺得書上說的最簡單明了。

進程中可以同時存在多個程序控制流程的線程,線程會共享進程范圍內(nèi)的資源,因此一個進程可以有多個線程。打個比方,進程就像一個大工廠,而線程就是工廠的工人,多個工人負責協(xié)同完成工廠的任務。

1.2 多線程的優(yōu)勢

發(fā)揮多處理器的強大能力

簡化建模過程

簡化異步事件處理機制

響應更靈敏的用戶界面

1.3 多線程安全性問題

多線程是一把雙刃劍,使用多線程時意味著對開發(fā)人員有一定的技術(shù)要求。可見學會了多線程技術(shù),就能寫出更優(yōu)雅的代碼了,哈哈~

多個線程同時訪問意味著“共享”變量,這些“共享”變量往往在其生命周期內(nèi)是可變的,這樣以來就極易出現(xiàn)多線程安全性問題。

什么是線程安全,這里給一個比較準確的定義:當多個線程訪問某各類時,這個類始終都能表現(xiàn)出正確的行為,那么就稱這個類是線程安全的。

二、Java 內(nèi)存模型

為什么要在多線程專題里涉及到 Java 內(nèi)存模型呢?我覺得它可以幫助我們更好的理解多線程的工作機制。

比如很多人都聽說過或了解過 volatile 關鍵字,都知道它能保證內(nèi)存可見性問題,但是理解起來總是太過抽象。如果你了解了 Java 內(nèi)存模型,它可以很好的幫助你理解這些問題。

Java 內(nèi)存模型規(guī)定了所有的變量都存儲在主內(nèi)存中(Main Memory)中(可以類比為物理硬件的主內(nèi)存)。每條線程都有自己的工作內(nèi)存(Working Memory),線程的工作內(nèi)存中保存了主內(nèi)存中的變量的拷貝,線程對變量的所有操作(讀取、賦值)都必須在自己的工作內(nèi)存中進行,而不能直接讀寫主內(nèi)存中的變量。

不同的線程之間無法訪問對方工作內(nèi)存中的變量,線程間變量值的傳遞均需要通過主內(nèi)存來完成。

如果你對 Java 內(nèi)存區(qū)域了解的話,很容易就會想工作內(nèi)存、主內(nèi)存與 Java 內(nèi)存區(qū)域中的堆、棧、方法區(qū)是否有一定關系呢?

如果在實例變量的角度來看,主內(nèi)存對應于 Java 堆中的對象實例數(shù)據(jù)部分,而工作內(nèi)存則對應于虛擬機棧中的部分區(qū)域。從更低層次來看,主內(nèi)存直接對應于物理硬件的內(nèi)存。

三、解決線程安全性問題

使用 Java 創(chuàng)建線程的幾種方式這里就不再贅述了,我們來了解幾種處理多線程安全性問題的方法。

3.1 synchronized 關鍵字

Java 提供了一種內(nèi)置的鎖機制(synchronized 關鍵字)來保證原子性與內(nèi)存可見性。關于原子性與內(nèi)存可見性問題會在講述 volatile 關鍵字時詳細的介紹,感興趣的可以關注后面的文章。

Java 的內(nèi)置鎖是一種互斥鎖,意味著最多只有一個線程能持有這種鎖。當線程 A 和線程 B 同時訪問臨界資源,如果線程 A 獲取鎖,線程 B 就必須等待或阻塞,A 不釋放 B 就只能等待下去。

由于每次只有一個線程執(zhí)行內(nèi)置鎖內(nèi)的代碼,因此被 synchronized 關鍵字保護的臨界資源會以原子(一組不可分割的單元)的方式執(zhí)行,多個線程間執(zhí)行時不會受到干擾,原子性與數(shù)據(jù)庫事務有相同的含義。

synchronized 關鍵字可以用來修飾方法和代碼塊,如果修飾非靜態(tài)方法和同步代碼塊,使用的鎖是當前對象,如果修飾靜態(tài)方法和靜態(tài)代碼塊,使用的是當前類的 Class 對象作為鎖。

使用方式如下

public class SyncTest {
    private Integer num = 1;
    
    public int numAutoIncrement() {
        synchronized (this) {
            return num ++;
        }
    }

    public static void main(String[] args) {
        SyncTest syncTest = new SyncTest();

        // 開啟 10 個線程
        for (int i = 0; i < 10; i++) {
            new Thread(() -> 
                    System.out.println(Thread.currentThread().getName() 
                            + ":" + syncTest.numAutoIncrement())
            ).start();
        }
    }
}

3.2 使用原子類

jdk1.5 之后 java.util.concurrent.atomic 包下引入了諸如 AtomicInteger、AtomicLong 等特殊的原子性變量類。

這些變量類底層使用 CAS 算法與 volatile 關鍵字確保對所有的計數(shù)器操作都能保證原子性與可見性,也就解決了多線程安全問題。

使用方式如下

public class SyncTest {
    private AtomicInteger atomicInteger = new AtomicInteger(1);
    
    public int numAutoIncrement() {
        return atomicInteger.getAndIncrement();
    }

    public static void main(String[] args) {
        SyncTest syncTest = new SyncTest();

        for (int i = 0; i < 10; i++) {
            new Thread(() -> 
                    System.out.println(Thread.currentThread().getName() 
                            + ":" + syncTest.numAutoIncrement())
            ).start();
        }
    }
}

3.3 使用顯示 Lock 鎖

jdk1.5 之前,解決多線程共享對象訪問的機制只有 synchronizedvolatile。jdk1.5 新增了一種新的機制:ReentrantLock。ReentrantLock 并不是為替代內(nèi)置鎖而生的,當內(nèi)置鎖機制不適用時,可以考慮使用這種更靈活的加鎖機制。

使用方式如下

public class SyncTest {
    private Lock lock = new ReentrantLock();
    private Integer num = 1;
    
    public int numAutoIncrement() {
        lock.lock();
        try {
            return num++;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        SyncTest syncTest = new SyncTest();

        for (int i = 0; i < 10; i++) {
            new Thread(() -> 
                    System.out.println(Thread.currentThread().getName() 
                            + ":" + syncTest.numAutoIncrement())
            ).start();
        }
    }
}

從上面的代碼可以看出來,使用顯示鎖機制相對內(nèi)置鎖要麻煩一些,使用時要注意必須在 finally 語句塊中釋放鎖,否則當出現(xiàn)異常時,獲取到的鎖永遠不會被釋放,在代碼中存在這種情況無疑是一種定時炸彈。

顯示鎖相較于內(nèi)置鎖還提供了等待可中斷、公平與非公平等功能,當然還有一個優(yōu)點是顯示鎖更加靈活。

PS:
這篇博文中很多知識點拿出來都可以多帶帶寫一篇文章,這里只是總結(jié)了一部分重要的知識點,先讓大家對多線程有一個感性的認識。后面會陸續(xù)的補充并發(fā)編程系列的文章。如果大家覺得寫得還行的話,請持續(xù)關注后面的文章。

參考資料

《Java 并發(fā)編程實戰(zhàn)》
《深入理解 Java 虛擬機》

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/77206.html

相關文章

  • jvm原理

    摘要:在之前,它是一個備受爭議的關鍵字,因為在程序中使用它往往收集器理解和原理分析簡稱,是后提供的面向大內(nèi)存區(qū)數(shù)到數(shù)多核系統(tǒng)的收集器,能夠?qū)崿F(xiàn)軟停頓目標收集并且具有高吞吐量具有更可預測的停頓時間。 35 個 Java 代碼性能優(yōu)化總結(jié) 優(yōu)化代碼可以減小代碼的體積,提高代碼運行的效率。 從 JVM 內(nèi)存模型談線程安全 小白哥帶你打通任督二脈 Java使用讀寫鎖替代同步鎖 應用情景 前一陣有個做...

    lufficc 評論0 收藏0
  • 線程編程完全指南

    摘要:在這個范圍廣大的并發(fā)技術(shù)領域當中多線程編程可以說是基礎和核心,大多數(shù)抽象并發(fā)問題的構(gòu)思與解決都是基于多線程模型來進行的。一般來說,多線程程序會面臨三類問題正確性問題效率問題死鎖問題。 多線程編程或者說范圍更大的并發(fā)編程是一種非常復雜且容易出錯的編程方式,但是我們?yōu)槭裁催€要冒著風險艱辛地學習各種多線程編程技術(shù)、解決各種并發(fā)問題呢? 因為并發(fā)是整個分布式集群的基礎,通過分布式集群不僅可以大...

    mengera88 評論0 收藏0
  • 【進階1-4期】JavaScript深入帶你走進內(nèi)存機制

    摘要:引擎對堆內(nèi)存中的對象進行分代管理新生代存活周期較短的對象,如臨時變量字符串等。內(nèi)存泄漏對于持續(xù)運行的服務進程,必須及時釋放不再用到的內(nèi)存。 (關注福利,關注本公眾號回復[資料]領取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導) 本周正式開始前端進階的第一期,本周的主題是調(diào)用堆棧,今天是第4天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了解本進階計劃...

    不知名網(wǎng)友 評論0 收藏0
  • 帶你了解集合世界的fail-fast機制 和 CopyOnWriteArrayList 源碼詳解

    摘要:體現(xiàn)的就是適配器模式。數(shù)組對象集合世界中的機制機制集合世界中比較常見的錯誤檢測機制,防止在對集合進行遍歷過程當中,出現(xiàn)意料之外的修改,會通過異常暴力的反應出來。而在增強循環(huán)中,集合遍歷是通過進行的。 前言 學習情況記錄 時間:week 2 SMART子目標 :Java 容器 記錄在學習Java容器 知識點中,關于List的重點知識點。 知識點概覽: 容器中的設計模式 從Array...

    young.li 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<