亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

synchronized關(guān)鍵字使用詳解

Jeffrrey / 1615人閱讀

摘要:基本使用同步代碼塊同步代碼塊延時(shí)秒,方便后面測試作用代碼塊時(shí),方法中的,是指調(diào)用該方法的對象。那么這個(gè)時(shí)候使用關(guān)鍵字就需要注意了推薦使用同步代碼塊,同步的代碼塊中傳入外部定義的一個(gè)變量。

簡述

計(jì)算機(jī)單線程在執(zhí)行任務(wù)時(shí),是嚴(yán)格按照程序的代碼邏輯,按照順序執(zhí)行的。因此單位時(shí)間內(nèi)能執(zhí)行的任務(wù)數(shù)量有限。為了能在相同的時(shí)間內(nèi)能執(zhí)行更多的任務(wù),就必須采用多線程的方式來執(zhí)行(注意:多線程模式無法減少單次任務(wù)的執(zhí)行時(shí)間)。但是引入了多線程之后,又帶來了線程安全的問題。而為了解決線程安全的問題,又引入了鎖的概念。java中常用的鎖有synchronizedlock兩種,本文我們來分析synchronized的具體用法和使用注意事項(xiàng)。

基本使用

同步代碼塊

/**
 * 同步代碼塊
 * @throws Exception
 */
public void synchronizedCode() {
    try {
        synchronized (this) {
            System.out.println(getCurrentTime() + ":I am synchronized Code");
            Thread.sleep(5000);//延時(shí)5秒,方便后面測試
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

作用代碼塊時(shí),synchronized方法中的this,是指調(diào)用該方法的對象。需要主要的是,synchronized作用代碼塊時(shí),只會(huì)鎖住這一小塊代碼。代碼塊的上下部分的其他代碼在所有的線程仍然是能同時(shí)訪問的。同時(shí)需要注意的是每個(gè)對象有用不同的鎖。即不會(huì)阻塞不同對象的調(diào)用。

同步方法

/**
  * 同步方法
  */
public synchronized void synchronizedMethod() {
    try {
        System.out.println(getCurrentTime() + ":I am synchronized method");
        Thread.sleep(5000);//延時(shí)5秒,方便后面測試
    } catch (Exception e) {
        e.printStackTrace();
    }
}

synchronized作用在方法上,其實(shí)是缺省了this關(guān)鍵字,實(shí)際上是synchronized(this)。this是指調(diào)用該方法的對象。此鎖也不會(huì)阻塞不同對象之間的調(diào)用。

同步靜態(tài)方法

/**
* 同步靜態(tài)方法
*/
public synchronized static void synchronizedStaticMethod() {
    try {
        System.out.println(getCurrentTime() + ":I am synchronized static method");
        Thread.sleep(5000);//延時(shí)5秒,方便后面測試
    } catch (Exception e) {
        e.printStackTrace();
    }
}

使用方式和作用普通方式相同,唯一需要注意的地方是此鎖所有對象共用,即不同對象之間會(huì)阻塞調(diào)用。

測試準(zhǔn)備

簡單說明一下:有一個(gè)線程池,在執(zhí)行多任務(wù)時(shí)使用。每個(gè)同步方法或者代碼塊中都有一個(gè)休眠5秒的動(dòng)作,利用打印時(shí)間加休眠來看線程之間是否有阻塞效果。然后有一個(gè)1秒打印一次時(shí)間的方法。

public class Synchronized {
    //打印時(shí)間時(shí)格式化
    public static final String timeFormat = "HH:mm:ss";
    //執(zhí)行多任務(wù)的線程池
    public static final ExecutorService executor = Executors.newFixedThreadPool(4);

    /**
     * 同步代碼塊
     * @throws Exception
     */
    public void synchronizedCode() {
        try {
            synchronized (this) {
                System.out.println(getCurrentTime() + ":I am synchronized Code");
                Thread.sleep(5000);//延時(shí)5秒,方便后面測試
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 同步方法
     */
    public synchronized void synchronizedMethod() {
        try {
            System.out.println(getCurrentTime() + ":I am synchronized method");
            Thread.sleep(5000);//延時(shí)5秒,方便后面測試
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 同步靜態(tài)方法
     */
    public synchronized static void synchronizedStaticMethod() {
        try {
            System.out.println(getCurrentTime() + ":I am synchronized static method");
            Thread.sleep(5000);//延時(shí)5秒,方便后面測試
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 循環(huán)打印時(shí)間
     */
    public static void printNumber() {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        printOnceASecond();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    /**
     * 一秒打印一次時(shí)間
     *
     * @throws Exception
     */
    public static void printOnceASecond() throws Exception {
        System.out.println(getCurrentTime());
        Thread.sleep(1000);
    }

    /**
     * 獲取當(dāng)前時(shí)間
     *
     * @return
     */
    public static String getCurrentTime() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(timeFormat));
    }
}

OK,接下來我們就來測試下鎖的互斥性以及使用注意事項(xiàng)(都是多線程的情況下)。

開始測試

同一個(gè)對象同步代碼塊

public static void main(String[] args) throws Exception {
    printNumber();//控制臺(tái)循環(huán)打印時(shí)間
    Synchronized es = new Synchronized();
    executor.execute(() -> es.synchronizedCode());
    executor.execute(() -> es.synchronizedCode());
}

execute

20:34:41:I am synchronized Code
20:34:41
20:34:42
20:34:43
20:34:44
20:34:45
20:34:46:I am synchronized Code

同步代碼塊中休眠5秒,導(dǎo)致另外一個(gè)線程阻塞5秒后再執(zhí)行。說明代同步碼塊會(huì)阻塞同一個(gè)對象的不同線程之間的調(diào)用(同步方法和同步靜態(tài)方法也會(huì)阻塞同一個(gè)對象的不同線程之間的調(diào)用,此處省略測試代碼)

不同對象同步代碼塊

public static void main(String[] args) throws Exception {
    printNumber();//控制臺(tái)循環(huán)打印時(shí)間
    Synchronized es = new Synchronized();
    Synchronized es1 = new Synchronized();
    executor.execute(() -> es.synchronizedCode());
    executor.execute(() -> es1.synchronizedCode());
}

execute

20:44:34:I am synchronized Code
20:44:34:I am synchronized Code

由結(jié)果可以看出,不同對象之間代碼塊鎖互不影響(多線程也一樣)。原因是因?yàn)榇a塊中synchronized (this)

鎖的是當(dāng)前調(diào)用對象,不同對象之間不是同一把鎖,因此互不影響(同步方法原理也是如此,省略測試代碼)。

同一對象同步代碼塊和方法

public static void main(String[] args) throws Exception {
    printNumber();//控制臺(tái)循環(huán)打印時(shí)間
    Synchronized es = new Synchronized();
    executor.execute(() -> es.synchronizedCode());
    executor.execute(() -> es.synchronizedMethod());
}

execute

20:51:27:I am synchronized method
20:51:27
20:51:28
20:51:29
20:51:30
20:51:31
20:51:32:I am synchronized Code

因?yàn)橥酱a塊和同步方法,都是鎖當(dāng)前調(diào)用對象,因此執(zhí)行后打印上述結(jié)果應(yīng)該在意料之中?;谶@樣的特性,實(shí)際開發(fā)在使用spring的時(shí)候就需要注意了,我們的bean交給spring容器管理之后,默認(rèn)都是單例的。那么這個(gè)時(shí)候使用synchronized關(guān)鍵字就需要注意了(推薦使用同步代碼塊,同步的代碼塊中傳入外部定義的一個(gè)變量)。

不同對象靜態(tài)同步方法

public static void main(String[] args) throws Exception {
    printNumber();//控制臺(tái)循環(huán)打印時(shí)間
    Synchronized es = new Synchronized();
    Synchronized es1 = new Synchronized();
    executor.execute(() -> es.synchronizedStaticMethod());
    executor.execute(() -> es1.synchronizedStaticMethod());
}

execute

21:05:39:I am synchronized static method
21:05:40
21:05:41
21:05:42
21:05:43
21:05:44:I am synchronized static method

由上述結(jié)果可以看出來,靜態(tài)同步方法會(huì)阻塞所有的對象。原因是所有的靜態(tài)同步方法都是占用的同一把鎖。

相同對象同步方法和靜態(tài)同步方法

public static void main(String[] args) throws Exception {
    printNumber();//控制臺(tái)循環(huán)打印時(shí)間
    Synchronized es = new Synchronized();
    executor.execute(() -> es.synchronizedMethod());
    executor.execute(() -> es.synchronizedStaticMethod());
}

execute

21:11:03:I am synchronized static method
21:11:03:I am synchronized method

由此結(jié)果可以看出,同步方法和靜態(tài)同步方法之間不會(huì)造成阻塞的現(xiàn)象。因?yàn)樗麄冩i的對象不一樣。同步方法占用的鎖是調(diào)用對象,靜態(tài)同步方法鎖的是編譯后的class對象(類鎖)。

總結(jié)

同一個(gè)對象,同步方法、同步代碼塊之間互斥,同時(shí)和自己也互斥。靜態(tài)同步方法只和自己互斥

不同對象之間,同步方法、同步代碼塊不會(huì)互斥。靜態(tài)同步方法會(huì)互斥

synchronized在占用鎖時(shí),必須精確到某一個(gè)具體的對象

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/74420.html

相關(guān)文章

  • 一起學(xué)并發(fā)編程 - synchronized詳解

    摘要:每個(gè)對象只有一個(gè)鎖與之相關(guān)聯(lián)。實(shí)現(xiàn)同步則是以系統(tǒng)開銷作為代價(jià),甚至可能造成死鎖,所以盡量避免濫用。這種機(jī)制確保了同一時(shí)刻該類實(shí)例,所有聲明為的函數(shù)中只有一個(gè)方法處于可執(zhí)行狀態(tài),從而有效避免了類成員變量訪問沖突。 synchronized是JAVA語言的一個(gè)關(guān)鍵字,使用 synchronized 來修飾方法或代碼塊的時(shí)候,能夠保證多個(gè)線程中最多只有一個(gè)線程執(zhí)行該段代碼 ... 概述 ...

    acrazing 評論0 收藏0
  • Java中wait、notify、notifyAll使用詳解

    摘要:用法中規(guī)定,在調(diào)用者三個(gè)方法時(shí),當(dāng)前線程必須獲得對象鎖。作用方法作用線程自動(dòng)釋放占有的對象鎖,并等待。當(dāng)生產(chǎn)者生產(chǎn)了一個(gè)數(shù)據(jù)或者消費(fèi)者消費(fèi)了一個(gè)數(shù)據(jù)之后,使用方法來通知所有等待當(dāng)前對象鎖的線程,但是一次只會(huì)有一個(gè)等待的線程能拿到鎖。 基礎(chǔ)知識 首先我們需要知道,這幾個(gè)都是Object對象的方法。換言之,Java中所有的對象都有這些方法。 public final native void...

    rozbo 評論0 收藏0
  • Java synchronized 多線程同步問題詳解

    摘要:同步代碼塊二類,鎖是小括號中的類對象對象。因?yàn)閷τ谕粋€(gè)實(shí)例對象,各線程之間訪問其中的同步方法是互斥的。優(yōu)化同步代碼塊的方式有,減少同步區(qū)域或減小鎖的范圍。 版權(quán)聲明:本文由吳仙杰創(chuàng)作整理,轉(zhuǎn)載請注明出處:https://segmentfault.com/a/1190000009225706 1. 引言 在 Java 多線程編程中,我們常需要考慮線程安全問題,其中關(guān)鍵字 synchro...

    Eidesen 評論0 收藏0
  • 后臺(tái)開發(fā)常問面試題集錦(問題搬運(yùn)工,附鏈接)

    摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...

    spacewander 評論0 收藏0
  • 后臺(tái)開發(fā)常問面試題集錦(問題搬運(yùn)工,附鏈接)

    摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...

    xfee 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<