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

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

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

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

1. synchronized 的基本概念

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

2. synchronized 的兩種使用方式

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

2.1 方法級(jí)別

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

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

2.2 代碼塊級(jí)別

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

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

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

3. synchronized 的示例

示例1

在下面的示例中,我們定義了一個(gè)計(jì)數(shù)器 Counter,在 Counter 的 run() 方法中使用 synchronized 關(guān)鍵字來(lái)保證多個(gè)線(xiàn)程對(duì) count 變量的訪(fǎng)問(wèn)安全。我們創(chuàng)建了 10 個(gè)線(xiàn)程,并且每個(gè)線(xiàn)程對(duì)計(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è)線(xiàn)程,每個(gè)線(xiàn)程對(duì)計(jì)數(shù)器進(jìn)行了 1000 次增加操作,這種并發(fā)場(chǎng)景下如果沒(méi)有加鎖機(jī)制,將會(huì)導(dǎo)致數(shù)據(jù)不一致。但是通過(guò)使用 synchronized 關(guān)鍵字的加鎖機(jī)制,我們保證了計(jì)數(shù)器的安全訪(fǎng)問(wèn),并且最終輸出的計(jì)數(shù)器的值也是正確的。

示例2

模擬在取款過(guò)程中可能出現(xiàn)的問(wè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() + " 開(kāi)始取款");
        try {
            // 模擬取款過(guò)程中的延遲
            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的對(duì)比結(jié)果:

不加synchronized的結(jié)果:

Thread 1 開(kāi)始取款
Thread 2 開(kāi)始取款
Thread 2 成功取款: 700
Thread 2 取款后余額為: 300
Thread 1 成功取款: 500
Thread 1 取款后余額為: -200

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

加上synchronized的結(jié)果:

Thread 1 開(kāi)始取款
Thread 1 成功取款: 500
Thread 1 取款后余額為: 500
Thread 2 開(kāi)始取款
Thread 2 余額不足
Thread 2 取款后余額為: 500

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

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

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

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

5. 總結(jié)

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

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

相關(guān)文章

  • Java類(lèi)成員訪(fǎng)問(wèn)權(quán)限控制知識(shí)總結(jié)

    Java類(lèi)成員訪(fǎng)問(wèn)權(quán)限控制知識(shí)總結(jié)

    這篇文章主要介紹了Java類(lèi)成員訪(fǎng)問(wèn)權(quán)限控制知識(shí)總結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(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)化部署,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-06-06
  • VSCode+Gradle搭建Java開(kāi)發(fā)環(huán)境實(shí)現(xiàn)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新評(píng)論