最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java線程安全中的原子性淺析

 更新時間:2023年02月21日 10:27:39   作者:綠仔牛奶_  
這篇文章主要介紹了Java線程安全中的原子性,原子性是指一條線程在執(zhí)行一系列程序指令操作時,該線程不可中斷。一旦出現中斷,那么就可能會導致程序執(zhí)行前后的結果不一致

何為原子性

原子性:一條線程在執(zhí)行一系列程序指令操作時,該線程不可中斷。一旦出現中斷,那么就可能會導致程序執(zhí)行前后的結果不一致。與數據庫中的原子性(事務管理體現)是相同的

概括:一段程序只能由一條線程去完整的執(zhí)行,不能被多個線程干擾執(zhí)行

以最經典的轉賬為例,甲向乙的賬戶轉賬500這個轉賬行為就包含了兩個操作:分別是1. 甲的賬戶-500 2. 乙的賬戶 +500但如果此時不能保證原子性操作就可能會出現甲的賬戶減了500但是乙的賬戶沒有加500的情況

首先我們先來區(qū)分哪些是原子操作哪些非原子操作:

int a = 1; // (1)
int b = a; // (2) 
a += b;    // (3)

(1)一個操作,就是將值“1” 賦給 變量a

(2)兩個操作,首先獲取a的值,然后將a的值賦給b

(3)四個操作,首先獲取b的值,再獲取a的值,再將a與b的值相加,再將相加后的值賦給a

所以只有(1)和(3)屬于原子操作,(2)不構成原子操作

上述舉例,我們清楚了原子操作就是一個不可分割的操作。

下面我們來看線程安全的原子性示例:

測試代碼:

public class Demo{
    public static void main(String[] args) {
        Temp task = new Temp();
        // 啟動100條線程
        for (int i = 1; i <= 100 ; i++) {
            new Thread(task).start();
        }
    }
}
class Temp implements Runnable{
    private int count = 0;
    @Override
    public void run() {
        // 線程任務:將count
        for (int i = 1; i <= 100; i++) {
            count++;
            System.out.println(Thread.currentThread().getName()+"::count====>>"+count);
        }
    }
}

上述代碼實現將Count從0加到10000,每一條線程控制count加100,100條線程啟動執(zhí)行實現。但是在執(zhí)行過程中會發(fā)現會出現幾次無法達到10000的結果,產生的原因就是假設當某一條線程在執(zhí)行count累加時執(zhí)行到了count=97時(也就是該線程執(zhí)行失敗,并且提交了執(zhí)行失敗的結果)cpu被其他線程拿到,那么其他線程繼續(xù)拿到count=97進行累加,這樣就導致最后結果不準確這個時候線程就不是安全的,也就是說我們這段程序是不具備原子性的。

但是有時效果不是很明顯,建議可以將線程數增加到500條;

那么原子性的問題如何解決呢?

解決方法

加鎖–> 悲觀鎖(阻塞同步)

利用synchronized修飾的同步方法、同步代碼塊啥的,隨便你怎么上鎖都可以,本質上的解決機理就是保證線程任務同時只能被一條線程執(zhí)行,在執(zhí)行完畢之前其他線程無法拿到執(zhí)行權。由此來保證線程的原子性

從時間維度上來講,某一時刻只允許一條線程執(zhí)行線程任務,其他線程就處于阻塞狀態(tài),這種利用阻塞其他線程的方式就稱為阻塞同步也叫做互斥同步。大大降低了執(zhí)行效率和性能

這種解決方式采用了悲觀的并發(fā)策略,synchronized也被稱為悲觀鎖,為什么說是悲觀?因為程序在加鎖之初就默認每一次線程操作共享資源時都會被其他線程干擾。即在不進行同步干預的情況下,程序默認每次線程操作共享資源都會存在其他線程的競爭繼而導致程序執(zhí)行出現問題。阻塞同步也就是做出了最壞的打算,故稱為悲觀鎖

使用原子類( Atomic )–> 樂觀鎖(非阻塞同步)

為什么還要使用原子類?

because 利用synchronized加鎖去解決原子性問題,性能太低了。如果我們的程序線程數量太大,那每次線程任務只能被單條線程執(zhí)行,效率太低了

原子類是性能高效、線程安全。并且Java提供了比較全面的原子類供開發(fā)者使用,下面以AtomicInteger為例來說它的方法使用,多數原子類的方法都有些類似

// 導包
import java.util.concurrent.atomic.AtomicInteger;

AtomicInteger整型原子類

// 常用方法
public final int set(int newValue) //為當前對象賦值
public final int get() //獲取當前值
public final int getAndSet(int newValue)//獲取當前值然后重新賦值
public final int getAndIncrement()//先獲取當前值然后自增
public final int getAndDecrement() //先獲取當前值然后自減
public final int getAndAdd(int delta) //獲取當前值然后加上delta
boolean compareAndSet(int expect, int update) //如果當前值等于預期值,則以原子方式將該值設置為輸入值(update)

除了整型原子類之外還有如長整型原子類AtomicLong、布爾原子類AtomicBoolean、整型數組AtomicIntegerArray、長整型數組AtomicLongArray、引用數據類型數組AtomicReferenceArray等

CAS機制(Compare And Swap)

什么是CAS?

CAS( Compare And Swap )意為比較并交換,CAS的實現機制就是利用了非阻塞同步。

采用樂觀的并發(fā)策略,當程序運行中,我們不再利用阻塞其他線程來保證當前線程正確執(zhí)行的方式,而是作出最優(yōu)情況的解決方案,故而也被稱為樂觀鎖。

即每一次線程操作共享資源都會執(zhí)行成功并提交正確的結果,但是在將最新的結果提交時,需要與當前存儲的值進行比較就是進行一個新值與原值沖突檢測,比較完之后如果發(fā)現最新結果與當前值一致則說明執(zhí)行失敗,反之則是執(zhí)行成功然后替換到原值即可

我們依然用上述操作count作為示例,如下圖所示

可以看出,不論任何一條線程正在操作count,都可以與其他線程進行競爭。非阻塞同步大大的節(jié)省了線程阻塞和喚醒的性能開銷

下面談一下CAS具體的實現機制(CAS算法)

CAS實現主要用到三個操作數,分別是 內存地址S、原值(預期值)A、新值B

當線程向主內存中提交一個共享變量的新值B時,首先會將原值A與S處存儲的值進行比較,只有當兩個值相同時(沒有其他線程干擾),才能將新值B提交至主內存更新共享變量

CAS算法真正關注的是線程提交時的S處值與預期值是否相同,但仍然存在ABA漏洞,暫時不做深究

到此這篇關于Java線程安全中的原子性淺析的文章就介紹到這了,更多相關Java線程原子性內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • mybatis-plus 處理大數據插入太慢的解決

    mybatis-plus 處理大數據插入太慢的解決

    這篇文章主要介紹了mybatis-plus 處理大數據插入太慢的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • 基于SpringBoot項目遇到的坑--Date入參問題

    基于SpringBoot項目遇到的坑--Date入參問題

    這篇文章主要介紹了SpringBoot項目遇到的坑--Date入參問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 在SpringBoot中利用RocketMQ實現批量消息消費功能

    在SpringBoot中利用RocketMQ實現批量消息消費功能

    RocketMQ 是一款分布式消息隊列,支持高吞吐、低延遲的消息傳遞,對于需要一次處理多條消息的場景,RocketMQ 提供了批量消費的機制,這篇文章將展示如何在 Spring Boot 中實現這一功能,感興趣的小伙伴跟著小編一起來看看吧
    2024-11-11
  • springAop實現講解(看這篇夠了)

    springAop實現講解(看這篇夠了)

    AOP面向切面編程是一種編程范式,它通過將通用的橫切關注點(如日志、事務、權限控制等)與業(yè)務邏輯分離,使得代碼更加清晰、簡潔、易于維護,這篇文章主要介紹了springAop實現講解(看這篇夠了),需要的朋友可以參考下
    2024-02-02
  • java SpringBoot自定義注解,及自定義解析器實現對象自動注入操作

    java SpringBoot自定義注解,及自定義解析器實現對象自動注入操作

    這篇文章主要介紹了java SpringBoot自定義注解,及自定義解析器實現對象自動注入操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • druid連接池的參數配置示例全面解析

    druid連接池的參數配置示例全面解析

    這篇文章主要為大家介紹了druid連接池的參數配置示例全面解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • Java中synchronized實現原理詳解

    Java中synchronized實現原理詳解

    這篇文章主要介紹了Java中synchronized實現原理詳解,涉及synchronized實現同步的基礎,Java對象頭,Monitor,Mark Word,鎖優(yōu)化,自旋鎖等相關內容,具有一定借鑒價值,需要的朋友可以參考下。
    2017-11-11
  • Java concurrency之AtomicReference原子類_動力節(jié)點Java學院整理

    Java concurrency之AtomicReference原子類_動力節(jié)點Java學院整理

    AtomicReference是作用是對"對象"進行原子操作。這篇文章主要介紹了Java concurrency之AtomicReference原子類,需要的朋友可以參考下
    2017-06-06
  • Java 如何快速實現一個連接池

    Java 如何快速實現一個連接池

    有沒有一個通用的庫可以快速實現一個線程池呢?得益于 Java 完善的生態(tài),前人們針對這種需要開發(fā)了一個通用庫:Apache Commons Pool(下文簡稱 ACP)。本質上來說,ACP 庫提供的是管理對象池的通用能力,當然也可以用來管理連接池了!
    2021-05-05
  • springsecurity基于token的認證方式

    springsecurity基于token的認證方式

    本文主要介紹了springsecurity基于token的認證方式,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08

最新評論

广丰县| 贺兰县| 区。| 焉耆| 额尔古纳市| 北票市| 金塔县| 石城县| 五峰| 赤城县| 阳西县| 班玛县| 旬阳县| 乌海市| 昌乐县| 贵阳市| 德庆县| 白河县| 英德市| 昌黎县| 买车| 鄂州市| 远安县| 抚顺县| 汉中市| 临桂县| 石嘴山市| 晴隆县| 若羌县| 延长县| 河源市| 朝阳区| 西畴县| 松滋市| 兰西县| 察雅县| 利川市| 嘉峪关市| 东方市| 康保县| 湘阴县|