亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解Java synchronized關(guān)鍵字的用法

 更新時(shí)間:2023年08月09日 16:51:44   作者:小虎哥的技術(shù)博客  
在多線程編程中常常使用鎖機(jī)制來確保同一時(shí)刻只有一個(gè)線程能夠修改共享內(nèi)存,在Java中一般是使用synchronized作為鎖機(jī)制,下面就讓我們來學(xué)習(xí)一下如何使用synchronized實(shí)現(xiàn)線程安全吧

當(dāng)你在洗手間時(shí),門是被鎖定的,這意味著沒有其他人可以走進(jìn)來并干擾你。同樣,在多線程編程中也存在這樣的問題,如果多個(gè)線程同時(shí)訪問同一塊共享內(nèi)存,那么就會產(chǎn)生競態(tài)條件,可能導(dǎo)致數(shù)據(jù)丟失或不一致的情況。為了避免這種情況,在多線程編程中使用鎖機(jī)制來確保同一時(shí)刻只有一個(gè)線程能夠修改共享內(nèi)存。Java 中使用 synchronized 作為鎖機(jī)制,讓我們來學(xué)習(xí)一下如何使用 synchronized 實(shí)現(xiàn)線程安全。

1. synchronized 的基本概念

在 Java 中,synchronized 可以用來鎖定一個(gè)對象,從而達(dá)到保護(hù)多個(gè)線程訪問共享數(shù)據(jù)的目的。當(dāng)一個(gè)線程獲取了 synchronized 鎖后,在未釋放鎖之前,其他線程不能獲取該鎖。相應(yīng)地,這個(gè)線程也不能獲取其他線程已經(jīng)獲取的鎖。

2. synchronized 的兩種使用方式

synchronized 關(guān)鍵字可以用在方法級別和代碼塊級別,下面分別介紹兩種使用方式。

2.1 方法級別

我們可以將 synchronized 用在方法級別上,這種情況下鎖定的對象是當(dāng)前對象(this)。

public class MyClass {
    public synchronized void myMethod() {
        // synchronized 代碼
    }
}

2.2 代碼塊級別

我們也可以將 synchronized 關(guān)鍵字用在代碼塊級別上,這種情況下鎖定的對象可以是當(dāng)前對象(this),也可以是任意一個(gè)對象。

public class MyClass {
    private final Object lock = new Object(); // 定義一個(gè)對象作為鎖
    public void myMethod() {
        synchronized (lock) {
            // synchronized 代碼
        }
    }
}

這種情況下,我們可以在任何時(shí)間使用 lock 對象來同步操作,當(dāng)然,也可以使用其他對象作為鎖。

3. synchronized 的示例

示例1

在下面的示例中,我們定義了一個(gè)計(jì)數(shù)器 Counter,在 Counter 的 run() 方法中使用 synchronized 關(guān)鍵字來保證多個(gè)線程對 count 變量的訪問安全。我們創(chuàng)建了 10 個(gè)線程,并且每個(gè)線程對計(jì)數(shù)器進(jìn)行 1000 次增操作,最后輸出計(jì)數(shù)器的值。

public class Test {
    public static void main(String[] args) {
        Counter counter = new Counter();
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(counter);
            threads[i].start();
        }
        for (int i = 0; i < threads.length; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("Final count: " + counter.getCount());
    }
    static class Counter implements Runnable {
        private int count = 0;
        public synchronized void increment() {
            count++;
        }
        public synchronized int getCount() {
            return count;
        }
        @Override
        public void run() {
            for (int i = 0; i < 1000; i++) {
                increment();
            }
        }
    }
}

在這個(gè)例子中,我們創(chuàng)建了 10 個(gè)線程,每個(gè)線程對計(jì)數(shù)器進(jìn)行了 1000 次增加操作,這種并發(fā)場景下如果沒有加鎖機(jī)制,將會導(dǎo)致數(shù)據(jù)不一致。但是通過使用 synchronized 關(guān)鍵字的加鎖機(jī)制,我們保證了計(jì)數(shù)器的安全訪問,并且最終輸出的計(jì)數(shù)器的值也是正確的。

示例2

模擬在取款過程中可能出現(xiàn)的問題:

class BankAccount {
    private int balance;
    public BankAccount(int initialBalance) {
        this.balance = initialBalance;
    }
    public synchronized void withdraw(int amount) {
        System.out.println(Thread.currentThread().getName() + " 開始取款");
        try {
            // 模擬取款過程中的延遲
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (amount <= balance) {
            balance -= amount;
            System.out.println(Thread.currentThread().getName() + " 成功取款: " + amount);
        } else {
            System.out.println(Thread.currentThread().getName() + " 余額不足");
        }
        System.out.println(Thread.currentThread().getName() + " 取款后余額為: " + balance);
    }
}
public class BankWithdrawalExample {
    public static void main(String[] args) {
        BankAccount account = new BankAccount(1000);
        Thread thread1 = new Thread(() -> account.withdraw(500), "Thread 1");
        Thread thread2 = new Thread(() -> account.withdraw(700), "Thread 2");
        thread1.start();
        thread2.start();
    }
}

在以上示例中,withdraw方法模擬了取款操作,并在其中加入了1秒的延遲。

withdraw方法加上和不加synchronized的對比結(jié)果:

不加synchronized的結(jié)果:

Thread 1 開始取款
Thread 2 開始取款
Thread 2 成功取款: 700
Thread 2 取款后余額為: 300
Thread 1 成功取款: 500
Thread 1 取款后余額為: -200

可以看到,由于沒有對銀行賬戶的取款方法進(jìn)行同步控制,兩個(gè)線程同時(shí)進(jìn)入了取款方法,導(dǎo)致賬戶余額計(jì)算錯(cuò)誤,出現(xiàn)了負(fù)數(shù)的情況。

加上synchronized的結(jié)果:

Thread 1 開始取款
Thread 1 成功取款: 500
Thread 1 取款后余額為: 500
Thread 2 開始取款
Thread 2 余額不足
Thread 2 取款后余額為: 500

可以看到,加上synchronized之后,兩個(gè)線程依次進(jìn)入了取款方法,避免了資源競爭的問題,從而保證了賬戶余額的正確性。

4. synchronized 的注意事項(xiàng)

使用 synchronized 時(shí),需要注意以下幾點(diǎn):

  • synchronized 關(guān)鍵字只能用于方法和代碼塊內(nèi)部,不能用于類和接口。
  • synchronized 鎖定的對象是當(dāng)前對象(this)或指定的對象,要注意鎖對象不應(yīng)該是一個(gè)字符串或者數(shù)字等常量,因?yàn)檫@樣可能導(dǎo)致死鎖情況。
  • synchronized 的開銷很大,每次加鎖和釋放鎖都需要進(jìn)行系統(tǒng)調(diào)用,需要注意性能問題。
  • synchronized 僅能解決單 JVM 內(nèi)的線程同步問題,對于多線程分布式環(huán)境,需要考慮分布式鎖的解決方案。

5. 總結(jié)

synchronized 關(guān)鍵字是 Java 中用來確保線程安全的基本機(jī)制。通過使用 synchronized,我們可以鎖定一個(gè)對象,從而確保同一時(shí)刻只有一個(gè)線程可以訪問該對象??梢詫?synchronized 用于方法級別和代碼塊級別,要注意鎖定的對象應(yīng)該是一個(gè)合適的對象,不能是一個(gè)常量。同時(shí),需要注意性能問題和分布式環(huán)境下的線程同步問題。

到此這篇關(guān)于詳解Java synchronized關(guān)鍵字的用法的文章就介紹到這了,更多相關(guān)Java synchronized關(guān)鍵字內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java類成員訪問權(quán)限控制知識總結(jié)

    Java類成員訪問權(quán)限控制知識總結(jié)

    這篇文章主要介紹了Java類成員訪問權(quán)限控制知識總結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Java利用jenkins做項(xiàng)目的自動(dòng)化部署

    Java利用jenkins做項(xiàng)目的自動(dòng)化部署

    這篇文章主要介紹了Java利用jenkins做項(xiàng)目的自動(dòng)化部署,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • VSCode+Gradle搭建Java開發(fā)環(huán)境實(shí)現(xiàn)

    VSCode+Gradle搭建Java開發(fā)環(huán)境實(shí)現(xiàn)

    這篇文章主要介紹了VSCode+Gradle搭建Java開發(fā)環(huán)境實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Java線程死鎖實(shí)例及解決方法

    Java線程死鎖實(shí)例及解決方法

    這篇文章主要介紹了Java線程死鎖實(shí)例及解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 使用@ConditionalOnProperty控制是否加載的操作

    使用@ConditionalOnProperty控制是否加載的操作

    這篇文章主要介紹了使用@ConditionalOnProperty控制是否加載的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • SpringBoot整合SpringSession實(shí)現(xiàn)分布式登錄詳情

    SpringBoot整合SpringSession實(shí)現(xiàn)分布式登錄詳情

    這篇文章主要介紹了SpringBoot整合SpringSession實(shí)現(xiàn)分布式登錄詳情,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-08-08
  • Sentinel熱門詞匯限流的實(shí)現(xiàn)詳解

    Sentinel熱門詞匯限流的實(shí)現(xiàn)詳解

    這篇文章主要介紹了使用Sentinel對熱門詞匯進(jìn)行限流的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • java定義二維數(shù)組的幾種寫法(小結(jié))

    java定義二維數(shù)組的幾種寫法(小結(jié))

    下面小編就為大家?guī)硪黄猨ava定義二維數(shù)組的幾種寫法(小結(jié))。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-10-10
  • IDEA .iml文件及.idea文件夾超詳細(xì)講解

    IDEA .iml文件及.idea文件夾超詳細(xì)講解

    iml文件是IntelliJ IDEA自己創(chuàng)建的模塊文件,用于java應(yīng)用開發(fā),存儲一些模塊相關(guān)的信息,比如一個(gè)Java組建,插件組建,Maven組建等,這篇文章主要介紹了IDEA .iml文件及.idea文件夾,需要的朋友可以參考下
    2023-09-09
  • JAVA中五個(gè)重定向的方式盤點(diǎn)

    JAVA中五個(gè)重定向的方式盤點(diǎn)

    頁面重定向即頁面從當(dāng)前請求的頁面,有條件或者定時(shí)跳轉(zhuǎn)到其他頁面,下面這篇文章主要給大家介紹了關(guān)于JAVA中五個(gè)重定向的方式,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12

最新評論