成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

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

acrazing / 2476人閱讀

摘要:每個(gè)對(duì)象只有一個(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í)行該段代碼 ...

概述

synchronized關(guān)鍵字可以作為函數(shù)的修飾符,也可作為函數(shù)內(nèi)的語句,也就同步方法同步代碼塊塊。細(xì)分為 instance variable(實(shí)例變量)、object reference(對(duì)象引用)、static method(靜態(tài)方法) 和 class literals(常量類)。

無論·synchronized·關(guān)鍵字加在方法上還是對(duì)象上,它獲取的都是對(duì)象鎖,而不是將一段代碼或一個(gè)函數(shù)當(dāng)作鎖,而且同步方法很可能還會(huì)被其他線程的對(duì)象訪問。

每個(gè)對(duì)象只有一個(gè)鎖(lock)與之相關(guān)聯(lián)。

實(shí)現(xiàn)同步則是以系統(tǒng)開銷作為代價(jià),甚至可能造成死鎖,所以盡量避免濫用。

同步方法: 使用 synchronized 標(biāo)記的方法,只有獲得該方法類實(shí)例的鎖才能執(zhí)行,否則所屬線程將被阻塞,方法一旦執(zhí)行,就獨(dú)占該鎖,直到該方法執(zhí)行完畢將鎖釋放,被阻塞的線程才能獲得鎖從而執(zhí)行。這種機(jī)制確保了同一時(shí)刻該類實(shí)例,所有聲明為 synchronized 的函數(shù)中只有一個(gè)方法處于可執(zhí)行狀態(tài),從而有效避免了類成員變量訪問沖突。

同步方法缺陷:若將一個(gè)大的方法聲明為 synchronized 將會(huì)大大的影響效率,典型的,若將線程類的方法 run() 聲明為 synchronized,由于在線程的整個(gè)生命期中它一直在運(yùn)行,因此將導(dǎo)致對(duì)本類任何 synchronized 方法的調(diào)用都不會(huì)成功。因此在這種環(huán)境下,可以使用同步代碼塊的方式

同步代碼塊: 除了方法前用synchronized關(guān)鍵字,還可以用于方法中的某個(gè)區(qū)塊中,表示只對(duì)該區(qū)域內(nèi)的資源進(jìn)行互斥操作。用法是: synchronized(this){/區(qū)塊/},它的作用域是當(dāng)前對(duì)象。也可以創(chuàng)建一個(gè)特殊的instance變量(它得是一個(gè)對(duì)象)來充當(dāng)鎖

寫法
類的范圍寫法,防止多個(gè)線程同時(shí)訪問這個(gè)類中的synchronized method,它可以對(duì)類的所有對(duì)象實(shí)例起作用
static synchronized void transferAccount() {
    //...
}
//等同
static void transferAccount() {
    synchronized(Bank.class) {
        //...
    }
}
對(duì)象實(shí)例內(nèi)寫法,多個(gè)線程同時(shí)訪問該對(duì)象的synchronized 方法,如果該對(duì)象實(shí)例有多個(gè)synchronized方法,任意線程訪問了其中的一個(gè)synchronized方法,剩余線程則不能并發(fā)訪問該對(duì)象中任何一個(gè)synchronized方法(不同對(duì)象實(shí)例的 synchronized方法是互不干擾的。其它線程依然可以并發(fā)訪問相同對(duì)象類不同實(shí)例中的synchronized方法,如果想做到在不同對(duì)象實(shí)例同步需要使用class literal的方式)
synchronized void transferAccount() {
    //...
}

void transferAccount() {
    synchronized(this) {
        //...
    }
}

private final byte[] LOCK = new byte[0]; // 特殊的實(shí)例化對(duì)象
void transferAccount() {
    synchronized(LOCK) {
        //...
    }
}
案例一:靜態(tài)同步方法
class Bank1 {
     synchronized static void transferAccount() {
        System.out.println("開始轉(zhuǎn)賬:" + Thread.currentThread().getName());
        try {
            Thread.sleep(3 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("轉(zhuǎn)賬完畢");
    }

     synchronized static void debit() {
        System.out.println("開始扣款:" + Thread.currentThread().getName());
        try {
            Thread.sleep(3 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("扣款完畢");
    }
}

public class BankMain {

    public static void main(String[] args) {
        new Thread(Bank1::transferAccount, "北京銀行").start();
        new Thread(Bank1::debit, "上海銀行").start();
    }
}
////////////////////////日志////////////////////////
開始轉(zhuǎn)賬:北京銀行
轉(zhuǎn)賬完畢
開始扣款:上海銀行
扣款完畢
////////////////////////日志////////////////////////

分析:通過日志看到在使用synchronized后,雖然是調(diào)用的不同方法,但是線程還是同步去執(zhí)行的(不加并發(fā)執(zhí)行,結(jié)果你懂得(^▽^))

案例二:同步方法單一對(duì)象鎖
class Bank2 implements Runnable {

    @Override
    public synchronized void run() {
        System.out.println("查詢數(shù)據(jù):" + Thread.currentThread().getName());
        System.out.println("開始轉(zhuǎn)賬:" + Thread.currentThread().getName());
        try {
            Thread.sleep(5 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("轉(zhuǎn)賬完畢");
    }
}

public class BankMain {

    public static void main(String[] args) {
        Bank2 bank2 = new Bank2();
        new Thread(bank2, "北京銀行").start();
        new Thread(bank2, "上海銀行").start();
    }
}
////////////////////////日志////////////////////////
查詢數(shù)據(jù):北京銀行
開始轉(zhuǎn)賬:北京銀行
轉(zhuǎn)賬完畢
查詢數(shù)據(jù):上海銀行
開始轉(zhuǎn)賬:上海銀行
轉(zhuǎn)賬完畢
////////////////////////日志////////////////////////

分析:方法同步執(zhí)行,誰獲得鎖誰先執(zhí)行

案例三:Lock對(duì)象鎖
class Bank3 implements Runnable {
    private final byte[] LOCK = new byte[0]; // 特殊的實(shí)例化變量

    @Override
    public void run() {
        System.out.println("查詢數(shù)據(jù):" + Thread.currentThread().getName());
        synchronized (LOCK) {//該種方式只能鎖
            System.out.println("開始轉(zhuǎn)賬:" + Thread.currentThread().getName());
            try {
                Thread.sleep(5 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("轉(zhuǎn)賬完畢");
        }
    }
}

public class BankMain {

    public static void main(String[] args) {
        Bank3 bank = new Bank3();
        new Thread(bank, "北京銀行").start();
        new Thread(bank, "上海銀行").start();
    }
}
////////////////////////日志////////////////////////
查詢數(shù)據(jù):北京銀行
查詢數(shù)據(jù):上海銀行
開始轉(zhuǎn)賬:北京銀行
轉(zhuǎn)賬完畢
開始轉(zhuǎn)賬:上海銀行
轉(zhuǎn)賬完畢
////////////////////////日志////////////////////////

分析:互斥部分上鎖,查詢數(shù)據(jù)部分則并發(fā)執(zhí)行

案例四:同步到多個(gè)對(duì)象鎖

前文說過一個(gè)實(shí)例對(duì)象一把鎖,在案例三案例四中,都只實(shí)例化了一個(gè)對(duì)象,當(dāng)對(duì)象為多實(shí)例化的時(shí)候,需使用class literal 的方式,它和synchronized static method方式產(chǎn)生的結(jié)果一樣,取得的鎖很特別,為當(dāng)前調(diào)用該方法對(duì)象所屬的類(而不再是由這個(gè)Class產(chǎn)生的某個(gè)具體對(duì)象了)。

class Bank4 implements Runnable {
    @Override
    public void run() {
        System.out.println("查詢數(shù)據(jù):" + Thread.currentThread().getName());
        synchronized (Bank4.class) {
            System.out.println("開始轉(zhuǎn)賬:" + Thread.currentThread().getName());
            try {
                Thread.sleep(5 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("轉(zhuǎn)賬完畢");
        }
    }
}

public class BankMain {

    public static void main(String[] args) {
        new Thread(new Bank4(), "北京銀行").start();
        new Thread(new Bank4(), "上海銀行").start();
    }
}

////////////////////////日志////////////////////////
查詢數(shù)據(jù):北京銀行
查詢數(shù)據(jù):上海銀行
開始轉(zhuǎn)賬:北京銀行
轉(zhuǎn)賬完畢
開始轉(zhuǎn)賬:上海銀行
轉(zhuǎn)賬完畢
////////////////////////日志////////////////////////

可以推斷:如果一個(gè)類中定義了一個(gè)synchronized static methodA,也定義了一個(gè) synchronized 的 instance methodB,該類同一個(gè)對(duì)象在多線程中分別訪問A和B兩個(gè)方法時(shí),并不會(huì)構(gòu)成同步,因?yàn)樗鼈兊逆i都不一樣。methodA的鎖是它的所屬Class,而methodB的鎖是當(dāng)前對(duì)象(該部分代碼未貼出,可以自己實(shí)現(xiàn)或者看GIT

- 說點(diǎn)什么

全文代碼:https://gitee.com/battcn/battcn-concurent/tree/master/Chapter1-1/battcn-thread/src/main/java/com/battcn/chapter5

個(gè)人QQ:1837307557

battcn開源群(適合新手):391619659

微信公眾號(hào):battcn(歡迎調(diào)戲)

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/67629.html

相關(guān)文章

  • 一起學(xué)并發(fā)編程 - sleep與wait的差異

    摘要:一般差異簡(jiǎn)單來說,是一個(gè)用于線程同步的實(shí)例方法。暫停當(dāng)前線程,不釋放任何鎖。用來線程間通信,使擁有該對(duì)象鎖的線程等待直到指定時(shí)間或。執(zhí)行對(duì)該對(duì)象加的同步代碼塊。 在JAVA的學(xué)習(xí)中,不少人會(huì)把sleep和wait搞混,認(rèn)為都是做線程的等待,下面主要介紹下這倆者是什么,及了解它們之間的差異和相似之處。 一般差異 簡(jiǎn)單來說,wait()是一個(gè)用于線程同步的實(shí)例方法。因?yàn)槎x在java.l...

    noONE 評(píng)論0 收藏0
  • 一起學(xué)并發(fā)編程 - 死鎖跟蹤分析

    摘要:上一章介紹過關(guān)鍵字,使用它可以給程序互斥部分加上一把鎖從而達(dá)到同步的效果,但錯(cuò)誤的用法會(huì)導(dǎo)致多個(gè)線程同時(shí)被阻塞死鎖死鎖多個(gè)線程同時(shí)被阻塞,它們中的一個(gè)或者全部都在等待某個(gè)資源被釋放。由于線程被無限期地阻塞,因此程序不可能正常終止。 上一章介紹過synchronized關(guān)鍵字,使用它可以給程序互斥部分加上一把鎖從而達(dá)到同步的效果,但錯(cuò)誤的用法會(huì)導(dǎo)致多個(gè)線程同時(shí)被阻塞.... 死鎖 死鎖...

    ACb0y 評(píng)論0 收藏0
  • 一起學(xué)并發(fā)編程 - 等待與通知

    摘要:如果有其它線程調(diào)用了相同對(duì)象的方法,那么處于該對(duì)象的等待池中的線程就會(huì)全部進(jìn)入該對(duì)象的鎖池中,從新爭(zhēng)奪鎖的擁有權(quán)。 wait,notify 和 notifyAll,這些在多線程中被經(jīng)常用到的保留關(guān)鍵字,在實(shí)際開發(fā)的時(shí)候很多時(shí)候卻并沒有被大家重視,而本文則是對(duì)這些關(guān)鍵字的使用進(jìn)行描述。 存在即合理 在java中,每個(gè)對(duì)象都有兩個(gè)池,鎖池(monitor)和等待池(waitset),每個(gè)...

    Meathill 評(píng)論0 收藏0
  • 學(xué)者福音!可能是最適合你的Java學(xué)習(xí)路線和方法推薦。

    摘要:學(xué)習(xí)完多線程之后可以通過下面這些問題檢測(cè)自己是否掌握,下面這些問題的答案以及常見多線程知識(shí)點(diǎn)的總結(jié)在這里。可選數(shù)據(jù)結(jié)構(gòu)與算法如果你想進(jìn)入大廠的話,我推薦你在學(xué)習(xí)完基礎(chǔ)或者多線程之后,就開始每天抽出一點(diǎn)時(shí)間來學(xué)習(xí)算法和數(shù)據(jù)結(jié)構(gòu)。 我自己總結(jié)的Java學(xué)習(xí)的系統(tǒng)知識(shí)點(diǎn)以及面試問題,已經(jīng)開源,目前已經(jīng) 35k+ Star。會(huì)一直完善下去,歡迎建議和指導(dǎo),同時(shí)也歡迎Star: https://...

    yanest 評(píng)論0 收藏0
  • 一起學(xué)并發(fā)編程 - Volatile關(guān)鍵字詳解

    摘要:比如用修飾的變量,就會(huì)確保變量在修改時(shí),其它線程是可見的。。多核環(huán)境中,多個(gè)線程分別在不同的中運(yùn)行,就意味著,多個(gè)線程都有可能將變量拷貝到當(dāng)前運(yùn)行的里。當(dāng)線程讀取變量時(shí),它將能看見被線程寫入的東西。 volatile是用來標(biāo)記一個(gè)JAVA變量存儲(chǔ)在主內(nèi)存(main memory)中,多線程讀寫volatile變量會(huì)先從高速緩存中讀取,但是寫入的時(shí)候會(huì)立即通過內(nèi)存總線刷到主存,同時(shí)內(nèi)存總...

    vpants 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<