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

Java中synchronized的幾種使用方法

 更新時(shí)間:2022年05月10日 10:50:55   作者:??Java中文社群????  
本文主要介紹了Java中synchronized的幾種使用方法,synchronized可用于修飾普通方法、靜態(tài)方法和代碼塊,下面詳細(xì)內(nèi)容介紹,需要的小伙伴可以參考一下

前言:

在 Java 語(yǔ)言中,保證線程安全性的主要手段是加鎖,而 Java 中的鎖主要有兩種:synchronized 和 Lock,我們今天重點(diǎn)來(lái)看一下 synchronized 的幾種用法。

用法簡(jiǎn)介

使用 synchronized 無(wú)需手動(dòng)執(zhí)行加鎖和釋放鎖的操作,我們只需要聲明 synchronized 關(guān)鍵字就可以了,JVM 層面會(huì)幫我們自動(dòng)的進(jìn)行加鎖和釋放鎖的操作。 synchronized 可用于修飾普通方法、靜態(tài)方法和代碼塊,接下來(lái)我們分別來(lái)看。

1、修飾普通方法

synchronized 修飾普通方法的用法如下:

/**
 * synchronized 修飾普通方法
 */
public synchronized void method() {
    // ....
}

當(dāng) synchronized 修飾普通方法時(shí),被修飾的方法被稱為同步方法,其作用范圍是整個(gè)方法,作用的對(duì)象是調(diào)用這個(gè)方法的對(duì)象。

2、修飾靜態(tài)方法

synchronized 修飾靜態(tài)方法和修飾普通方法類似,它的用法如下:

/**
 * synchronized 修飾靜態(tài)方法
 */
public static synchronized void staticMethod() {
    // .......
}

當(dāng) synchronized 修飾靜態(tài)方法時(shí),其作用范圍是整個(gè)程序,這個(gè)鎖對(duì)于所有調(diào)用這個(gè)鎖的對(duì)象都是互斥的。

所謂的互斥,指的是同一時(shí)間只能有一個(gè)線程能使用,其他線程只能排隊(duì)等待。

修飾普通方法 VS 修飾靜態(tài)方法

synchronized 修飾普通方法和靜態(tài)方法看似相同,但二者完全不同,對(duì)于靜態(tài)方法來(lái)說(shuō) synchronized 加鎖是全局的,也就是整個(gè)程序運(yùn)行期間,所有調(diào)用這個(gè)靜態(tài)方法的對(duì)象都是互斥的,而普通方法是針對(duì)對(duì)象級(jí)別的,不同的對(duì)象對(duì)應(yīng)著不同的鎖,比如以下代碼,同樣是調(diào)用兩次方法,但鎖的獲取完全不同

實(shí)現(xiàn)代碼如下:

import java.time.LocalDateTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class SynchronizedUsage {
    public static void main(String[] args) throws InterruptedException {
        // 創(chuàng)建線程池同時(shí)執(zhí)行任務(wù)
        ExecutorService threadPool = Executors.newFixedThreadPool(10);

        // 執(zhí)行兩次靜態(tài)方法
        threadPool.execute(() -> {
            staticMethod();
        });
        threadPool.execute(() -> {
            staticMethod();
        });
        // 執(zhí)行兩次普通方法
        threadPool.execute(() -> {
            SynchronizedUsage usage = new SynchronizedUsage();
            usage.method();
        });
        threadPool.execute(() -> {
            SynchronizedUsage usage2 = new SynchronizedUsage();
            usage2.method();
        });
    }

    /**
     * synchronized 修飾普通方法
     * 本方法的執(zhí)行需要 3s(因?yàn)橛?3s 的休眠時(shí)間)
     */
    public synchronized void method() {
        System.out.println("普通方法執(zhí)行時(shí)間:" + LocalDateTime.now());
        try {
            // 休眠 3s
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * synchronized 修飾靜態(tài)方法
     * 本方法的執(zhí)行需要 3s(因?yàn)橛?3s 的休眠時(shí)間)
     */
    public static synchronized void staticMethod() {
        System.out.println("靜態(tài)方法執(zhí)行時(shí)間:" + LocalDateTime.now());
        try {
            // 休眠 3s
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

以上程序的執(zhí)行結(jié)果如下: 

 從上述結(jié)果可以看出,靜態(tài)方法加鎖是全局的,針對(duì)的是所有調(diào)用者;而普通方法加鎖是對(duì)象級(jí)別的,不同的對(duì)象擁有的鎖也不同。

3、修飾代碼塊

我們?cè)谌粘i_(kāi)發(fā)中,最常用的是給代碼塊加鎖,而不是給方法加鎖,因?yàn)榻o方法加鎖,相當(dāng)于給整個(gè)方法全部加鎖,這樣的話鎖的粒度就太大了,程序的執(zhí)行性能就會(huì)受到影響,所以通常情況下,我們會(huì)使用 synchronized 給代碼塊加鎖,

它的實(shí)現(xiàn)語(yǔ)法如下:

public void classMethod() throws InterruptedException {
    // 前置代碼...
    // 加鎖代碼
    synchronized (SynchronizedUsage.class) {
        // ......
    }
    // 后置代碼...
}

從上述代碼我們可以看出,相比于修飾方法,修飾代碼塊需要自己手動(dòng)指定加鎖對(duì)象,加鎖的對(duì)象通常使用 this 或 xxx.class 這樣的形式來(lái)表示,比如以下代碼:

// 加鎖某個(gè)類
synchronized (SynchronizedUsage.class) {
    // ......
}

// 加鎖當(dāng)前類對(duì)象
synchronized (this) {
    // ......
}

this VS class

使用 synchronized 加鎖 this 和 xxx.class 是完全不同的,當(dāng)加鎖 this 時(shí),表示用當(dāng)前的對(duì)象進(jìn)行加鎖,每個(gè)對(duì)象都對(duì)應(yīng)了一把鎖;而當(dāng)使用 xxx.class 加鎖時(shí),表示使用某個(gè)類(而非類實(shí)例)來(lái)加鎖,它是應(yīng)用程序級(jí)別的,是全局生效的,

如以下代碼所示:

import java.time.LocalDateTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class SynchronizedUsageBlock {
    public static void main(String[] args) throws InterruptedException {
        // 創(chuàng)建線程池同時(shí)執(zhí)行任務(wù)
        ExecutorService threadPool = Executors.newFixedThreadPool(10);

        // 執(zhí)行兩次 synchronized(this)
        threadPool.execute(() -> {
            SynchronizedUsageBlock usage = new SynchronizedUsageBlock();
            usage.thisMethod();
        });
        threadPool.execute(() -> {
            SynchronizedUsageBlock usage2 = new SynchronizedUsageBlock();
            usage2.thisMethod();
        });

        // 執(zhí)行兩次 synchronized(xxx.class)
        threadPool.execute(() -> {
            SynchronizedUsageBlock usage3 = new SynchronizedUsageBlock();
            usage3.classMethod();
        });
        threadPool.execute(() -> {
            SynchronizedUsageBlock usage4 = new SynchronizedUsageBlock();
            usage4.classMethod();
        });
    }

    /**
     * synchronized(this) 加鎖
     * 本方法的執(zhí)行需要 3s(因?yàn)橛?3s 的休眠時(shí)間)
     */
    public void thisMethod() {
        synchronized (this) {
            System.out.println("synchronized(this) 加鎖:" + LocalDateTime.now());
            try {
                // 休眠 3s
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * synchronized(xxx.class) 加鎖
     * 本方法的執(zhí)行需要 3s(因?yàn)橛?3s 的休眠時(shí)間)
     */
    public void classMethod() {
        synchronized (SynchronizedUsageBlock.class) {
            System.out.println("synchronized(xxx.class) 加鎖:" + LocalDateTime.now());
            try {
                // 休眠 3s
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

以上程序的執(zhí)行結(jié)果如下: 

總結(jié)

synchronized 用 3 種用法,用它可以來(lái)修飾普通方法、靜態(tài)方法和代碼塊,其中最常用的是修飾代碼塊,而修飾代碼塊時(shí)需要指定一個(gè)加鎖對(duì)象,這個(gè)加鎖對(duì)象通常使用 this 或 xxx.class 來(lái)表示,當(dāng)使用 this 時(shí),表示使用當(dāng)前對(duì)象來(lái)加鎖,而使用 class 時(shí),表示表示使用某個(gè)類(非類對(duì)象實(shí)例)來(lái)加鎖,它是全局生效的。

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

相關(guān)文章

  • java格式化數(shù)值成貨幣格式示例

    java格式化數(shù)值成貨幣格式示例

    這篇文章主要介紹了java格式化數(shù)值成貨幣格式示例,格式化一個(gè)數(shù)值,比如123456789.123,希望顯示成"$123,456,789.123",需要的朋友可以參考下
    2014-04-04
  • String中intern方法的使用場(chǎng)景詳解

    String中intern方法的使用場(chǎng)景詳解

    這篇文章主要給大家介紹了關(guān)于String中intern方法的使用場(chǎng)景,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • JDBC下Idea添加mysql-jar包的詳細(xì)過(guò)程

    JDBC下Idea添加mysql-jar包的詳細(xì)過(guò)程

    這篇文章主要介紹了JDBC下Idea添加mysql-jar包的詳細(xì)過(guò)程,添加jar包首先到官網(wǎng)下載jar包,然后idea導(dǎo)入jar包,在就是檢查,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-11-11
  • SpringMVC?中的視圖使用?JSP的過(guò)程

    SpringMVC?中的視圖使用?JSP的過(guò)程

    本文介紹了如何在?SpringMVC?中使用?JSP?視圖,包括如何創(chuàng)建?JSP?視圖、配置?JSP?視圖解析器、以及如何在控制器方法中使用JSP視圖,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2023-07-07
  • 一文總結(jié)RabbitMQ中的消息確認(rèn)機(jī)制

    一文總結(jié)RabbitMQ中的消息確認(rèn)機(jī)制

    RabbitMQ消息確認(rèn)機(jī)制指的是在消息傳遞過(guò)程中,發(fā)送方發(fā)送消息后,接收方需要對(duì)消息進(jìn)行確認(rèn),以確保消息被正確地接收和處理,本文為大家整理了RabbitMQ中的消息確認(rèn)機(jī)制,需要的可以參考一下
    2023-06-06
  • Java設(shè)計(jì)模式中的適配器模式

    Java設(shè)計(jì)模式中的適配器模式

    這篇文章主要介紹了Java設(shè)計(jì)模式中的適配器模式, 適配器模式是將一個(gè)類的接口適配成用戶所期待的,一個(gè)適配允許通常因?yàn)榻涌诓患嫒荻荒茉谝黄鸸ぷ鞯念惞ぷ髟谝黄?做法是將類自己的接口包裹在一個(gè)已存在的類中,需要的朋友可以參考下
    2024-01-01
  • Spring Boot命令行運(yùn)行器的實(shí)現(xiàn)方法

    Spring Boot命令行運(yùn)行器的實(shí)現(xiàn)方法

    這篇文章主要介紹了Spring Boot命令行運(yùn)行器的實(shí)現(xiàn)方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-10-10
  • SpringBoot favicon Chrome設(shè)置問(wèn)題解決方案

    SpringBoot favicon Chrome設(shè)置問(wèn)題解決方案

    在本篇文章里小編給大家分享的是關(guān)于SpringBoot favicon Chrome設(shè)置問(wèn)題實(shí)例內(nèi)容,小的朋友們可以參考學(xué)習(xí)下。
    2020-02-02
  • 關(guān)于在IDEA中SpringBoot項(xiàng)目中activiti工作流的使用詳解

    關(guān)于在IDEA中SpringBoot項(xiàng)目中activiti工作流的使用詳解

    這篇文章主要介紹了關(guān)于在IDEA中SpringBoot項(xiàng)目中activiti工作流的使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Maven忽略單元測(cè)試及打包到Nexus的實(shí)現(xiàn)

    Maven忽略單元測(cè)試及打包到Nexus的實(shí)現(xiàn)

    我們的工程在打包發(fā)布時(shí)候,通常都需要忽略單元測(cè)試,以免因環(huán)境原因,無(wú)法通過(guò)單元測(cè)試而影響發(fā)布,本文主要介紹了Maven忽略單元測(cè)試及打包到Nexus的實(shí)現(xiàn),感興趣的可以了解一下
    2024-04-04

最新評(píng)論