欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java線程同步的四種方式詳解

 更新時間:2023年02月18日 16:05:22   投稿:wdc  
這篇文章主要介紹了Java線程同步的四種方式詳解,需要的朋友可以參考下

Java線程同步屬于Java多線程與并發(fā)編程的核心點,需要重點掌握,下面我就來詳解Java線程同步的4種主要的實現(xiàn)方式

什么是Java線程同步

當(dāng)使用多個線程來訪問同一個數(shù)據(jù)時,將會導(dǎo)致數(shù)據(jù)不準確,相互之間產(chǎn)生沖突,非常容易出現(xiàn)線程安全問題,如下圖所示:

Java線程同步的四種方式詳解(建議收藏)-mikechen的互聯(lián)網(wǎng)架構(gòu)

比如多個線程都在操作同一數(shù)據(jù),都打算修改商品庫存,這樣就會導(dǎo)致數(shù)據(jù)不一致的問題。

線程同步的真實意思,其實是“排隊”:幾個線程之間要排隊,一個一個對共享資源進行操作,而不是同時進行操作。

所以我們用同步機制來解決這些問題,加入同步鎖以避免在該線程沒有完成操作之前,被其他線程的調(diào)用,從而保證了該變量的唯一性和準確性。

Java線程同步的幾種方式

Java線程同步的四種方式詳解(建議收藏)-mikechen的互聯(lián)網(wǎng)架構(gòu)

1、使用synchronized關(guān)鍵字

這種方式比較靈活,修飾一個代碼塊,被修飾的代碼塊稱為同步語句塊。

其作用的范圍是大括號{}括起來的代碼,作用的對象是調(diào)用這個代碼塊的對象,如下格式:

synchronized(對象) { //得到對象的鎖,才能操作同步代碼
    需要被同步代碼;
}

通常沒有必要同步整個方法,使用synchronized代碼塊同步關(guān)鍵代碼即可。

具體的示例如下:

public class SynchronizedThread {
 
    class Bank {
 
        private int account = 200;
 
        public int getAccount() {
            return account;
        }
 
        /**
         * 用同步方法實現(xiàn)
         *
         * @param money
         */
        public synchronized void save(int money) {
            account += money;
        }
 
        /**
         * 用同步代碼塊實現(xiàn)
         *
         * @param money
         */
        public void save1(int money) {
            synchronized (this) {
                account += money;
            }
        }
    }
 
    class NewThread implements Runnable {
        private Bank bank;
 
        public NewThread(Bank bank) {
            this.bank = bank;
        }
 
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                // bank.save1(10);
                bank.save(10);
                System.out.println(i + "賬戶余額為:" + bank.getAccount());
            }
        }
 
    }
 
    /**
     * 建立線程,調(diào)用內(nèi)部類
     */
    public void useThread() {
        Bank bank = new Bank();
        NewThread new_thread = new NewThread(bank);
        System.out.println("線程1");
        Thread thread1 = new Thread(new_thread);
        thread1.start();
        System.out.println("線程2");
        Thread thread2 = new Thread(new_thread);
        thread2.start();
    }
 
    public static void main(String[] args) {
        SynchronizedThread st = new SynchronizedThread();
        st.useThread();
    }
 
}

2.使用ReentrantLock

ReentrantLock類是可重入、互斥、實現(xiàn)了Lock接口的鎖,它與使用synchronized方法具有相同的基本行為和語義,并且擴展了其能力。

private int account = 100;
//需要聲明這個鎖
private Lock lock = new ReentrantLock();
public int getAccount() {
    return account;
}
//這里不再需要synchronized 
public void save(int money) {
    lock.lock();
    try{
        account += money;
    }finally{
        lock.unlock();
    }

}

synchronized 與 Lock 的對比

ReentrantLock是顯示鎖,手動開啟和關(guān)閉鎖,別忘記關(guān)閉鎖;

synchronized 是隱式鎖,出了作用域自動釋放;

ReentrantLock只有代碼塊鎖,synchronized 有代碼塊鎖和方法鎖;

使用 ReentrantLock鎖,JVM 將花費較少的時間來調(diào)度線程,線程更好,并且具有更好的擴展性(提供更多的子類);

優(yōu)先使用順序:

ReentrantLock> synchronized 同步代碼塊> synchronized 同步方法

3.使用原子變量實現(xiàn)線程同步

為了完成線程同步,我們將使用原子變量(Atomic***開頭的)來實現(xiàn)。

比如典型代表:AtomicInteger類存在于java.util.concurrent.atomic中,該類表示支持原子操作的整數(shù),采用getAndIncrement方法以原子方法將當(dāng)前的值遞加。

具體示例如下:

private AtomicInteger account = new AtomicInteger(100);

public AtomicInteger getAccount() {
    return account;
}

public void save(int money) {
    account.addAndGet(money);
}

4.ThreadLocal實現(xiàn)線程同步

如果使用ThreadLocal管理變量,則每一個使用該變量的線程都獲得該變量的副本,副本之間相互獨立,這樣每一個線程都可以隨意修改自己的變量副本,而不會對其他線程產(chǎn)生影響,從而實現(xiàn)線程同步。

具體代碼示例如下:

//只改Bank類,其余代碼與上同
public class Bank{
    // 創(chuàng)建一個線程本地變量 ThreadLocal
    private static ThreadLocal<Integer> account = new ThreadLocal<Integer>(){
        @Override
        //返回當(dāng)前線程的"初始值" 
        protected Integer initialValue(){
            return 100;
        }
    };
    public void save(int money){
        //設(shè)置線程副本中的值
        account.set(account.get()+money);
    }
    public int getAccount(){
        //返回線程副本中的值 
        return account.get();
    }
}

以上就是Java線程同步的四種方式詳解的詳細內(nèi)容,更多關(guān)于Java線程同步的四種方式詳解的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java Date與String的相互轉(zhuǎn)換詳解

    Java Date與String的相互轉(zhuǎn)換詳解

    這篇文章主要介紹了Java Date與String的相互轉(zhuǎn)換詳解的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • Spring 處理 HTTP 請求參數(shù)注解的操作方法

    Spring 處理 HTTP 請求參數(shù)注解的操作方法

    這篇文章主要介紹了Spring 處理 HTTP 請求參數(shù)注解的操作方法,本文通過實例代碼給大家介紹的非常詳細,感興趣的朋友參考下吧
    2024-04-04
  • SpringBoot使用knife4j進行在線接口調(diào)試

    SpringBoot使用knife4j進行在線接口調(diào)試

    這篇文章主要介紹了SpringBoot使用knife4j進行在線接口調(diào)試,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java信號量全解析

    Java信號量全解析

    這篇文章主要介紹了Java信號量的相關(guān)資料,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2021-01-01
  • Spring中Controller應(yīng)用深入理解

    Spring中Controller應(yīng)用深入理解

    這篇文章主要介紹了Spring項目中的Controller,Spring Controller本身也是一個Spring Bean,只是它多提供了Web能力,只需要造類上提供@Controller注解即可
    2022-12-12
  • Springboot集成MongoDB無認證與開啟認證的配置方式

    Springboot集成MongoDB無認證與開啟認證的配置方式

    本文主要介紹了Springboot集成MongoDB無認證與開啟認證的配置方式,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-03-03
  • 詳解IntelliJ IDEA創(chuàng)建spark項目的兩種方式

    詳解IntelliJ IDEA創(chuàng)建spark項目的兩種方式

    這篇文章主要介紹了詳解IntelliJ IDEA創(chuàng)建spark項目的兩種方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • springboot配置mysql數(shù)據(jù)庫spring.datasource.url報錯的解決

    springboot配置mysql數(shù)據(jù)庫spring.datasource.url報錯的解決

    這篇文章主要介紹了springboot配置mysql數(shù)據(jù)庫spring.datasource.url報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • WebDriver中實現(xiàn)對特定的Web區(qū)域截圖方法

    WebDriver中實現(xiàn)對特定的Web區(qū)域截圖方法

    這篇文章主要介紹了WebDriver中實現(xiàn)對特定的Web區(qū)域截圖方法,本文直接給出實現(xiàn)代碼,需要的朋友可以參考下
    2015-06-06
  • Java 堆內(nèi)存分區(qū)的實現(xiàn)示例

    Java 堆內(nèi)存分區(qū)的實現(xiàn)示例

    本文主要介紹了Java 堆內(nèi)存分區(qū)的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04

最新評論