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

資訊專欄INFORMATION COLUMN

java多線程(4)synchronized的作用

Pandaaa / 944人閱讀

摘要:在多線程并發(fā)的情況下,有時(shí)就涉及到對(duì)于同一資源的讀寫,如果不進(jìn)行一些處理,容易出現(xiàn)數(shù)據(jù)混亂,結(jié)果和實(shí)際不一致等問(wèn)題。

在多線程并發(fā)的情況下,有時(shí)就涉及到對(duì)于同一資源的讀寫,如果不進(jìn)行一些處理,容易出現(xiàn)數(shù)據(jù)混亂,結(jié)果和實(shí)際不一致等問(wèn)題。java中可以使用synchronized關(guān)鍵字對(duì)資源鎖定。

synchronized的用法

synchronized有2種用法:
1.修飾代碼塊,以某個(gè)對(duì)象為鎖,鎖的范圍是指定的代碼塊。
2.修飾方法,其實(shí)也可以等價(jià)于修飾代碼塊,比如修飾普通方法:

synchronized void doxx(){
//.........
}

等價(jià)于

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

以當(dāng)前實(shí)體為鎖對(duì)象,整個(gè)方法都是在代碼塊中。也能修飾靜態(tài)方法:

public class Test{
    static synchronized void doxx(){
    //.........
    }
}

等價(jià)于

public class Test{
    static void doxx(){
        synchronized (Test.class){
        //.........
        }
    }
}
synchronized 修飾代碼塊

先舉一個(gè)反例demo:

import java.util.List;
import java.util.Random;

public    class Thread1 extends Thread{
    private List list;
    public Thread1(List list) {
        this.list=list;
    }
    @Override
    public void run() {
        try {
            for(int i=0;i<100;i++){
                Thread.sleep(10);//模擬處理一些業(yè)務(wù),這樣也更容易重現(xiàn)問(wèn)題
                int randon = new Random().nextInt();
                list.add(randon);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
    public static void main(String[] args) throws InterruptedException {
        List list = new ArrayList<>(1000);
        Thread1 t1 = new Thread1(list);
        t1.start();
        Thread1 t2 = new Thread1(list);
        t2.start();
        t1.join();
        t2.join();
        System.out.println("size="+list.size());
    }

執(zhí)行結(jié)果:

size=162

這個(gè)結(jié)果是不確定,每次執(zhí)行都可能不一樣。demo里啟動(dòng)了2個(gè)線程,每個(gè)執(zhí)行100次,按理list的數(shù)據(jù)量應(yīng)該會(huì)是200個(gè)。這個(gè)就是本文開始提到的,多個(gè)線程讀寫同一個(gè)對(duì)象時(shí),發(fā)生了數(shù)據(jù)異常。那么我們?cè)儆胹ynchronized對(duì)demo進(jìn)行小小的改造。

import java.util.List;
import java.util.Random;

public    class Thread1 extends Thread{
    private List list;
    public Thread1(List list) {
        this.list=list;
    }
    @Override
    public void run() {
        try {
            for(int i=0;i<100;i++){
                Thread.sleep(10);//模擬處理一些業(yè)務(wù),這樣也更容易重現(xiàn)問(wèn)題
                int randon = new Random().nextInt();
                synchronized (list) {//就只改這個(gè)地方
                    list.add(randon);
                }
            
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

main方法保持不變,結(jié)果如下:

size=200

可見使用synchronized關(guān)鍵字后,代碼的執(zhí)行結(jié)果恢復(fù)了正常。

synchronized修飾方法
import java.util.List;
import java.util.Random;

public    class Thread1 extends Thread{
    private List list;
    public Thread1(List list) {
        this.list=list;
    }
    public synchronized void  run() {
        try {
            for(int i=0;i<100;i++){
                Thread.sleep(10);//模擬處理一些業(yè)務(wù),這樣也更容易重現(xiàn)問(wèn)題
                int randon = new Random().nextInt();
                list.add(randon);
            
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

main方法不變,執(zhí)行結(jié)果:

size=150

這是很多人開始接觸多線程時(shí),會(huì)出現(xiàn)的錯(cuò)誤,明明對(duì)run方法用了synchronized 關(guān)鍵字怎么出來(lái)的結(jié)果是不對(duì)的。根據(jù)上面提到的我們把代碼轉(zhuǎn)變一下:

import java.util.List;
import java.util.Random;

public    class Thread1 extends Thread{
    private List list;
    public Thread1(List list) {
        this.list=list;
    }
    public  void  run() {
        try {
            synchronized(this){//把synchronized改到這個(gè)地方
                for(int i=0;i<100;i++){
                    Thread.sleep(10);//模擬處理一些業(yè)務(wù),這樣也更容易重現(xiàn)問(wèn)題
                    int randon = new Random().nextInt();
                    list.add(randon);
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

synchronized用在this上,所以t1.start()鎖定的是t1,t2.start()鎖定的是t2,2者鎖定的對(duì)象不同自然就沒(méi)有相應(yīng)的效果。

那是不是synchronized用在方法上就沒(méi)有作用呢?當(dāng)然不會(huì),先看下面的例子:

import java.util.Random;

public    class Thread1 extends Thread{
    private SyncList list;
    public Thread1(SyncList list) {
        this.list=list;
    }
    public  void  run() {
        try {
            for(int i=0;i<100;i++){
                Thread.sleep(10);//模擬處理一些業(yè)務(wù),這樣也更容易重現(xiàn)問(wèn)題
                int randon = new Random().nextInt();
                list.addList(randon);//注意這里
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
import java.util.ArrayList;
import java.util.List;

public class SyncList{
    
    private List list;
    
    public SyncList(List list) {
        this.list = list;
    }
    
    public void addList(E obj){
        list.add(obj);
    }
    public List getList() {
        return list;
    }
}
    public static void main(String[] args) throws InterruptedException {
        SyncList list = new SyncList(new ArrayList<>(1000));
        Thread1 t1 = new Thread1(list);
        t1.start();
        Thread1 t2 = new Thread1(list);
        t2.start();
        t1.join();
        t2.join();
        System.out.println("size="+list.getList().size());
}

執(zhí)行結(jié)果:

size=161

修改一下SyncList:

import java.util.ArrayList;
import java.util.List;

public class SyncList{
    
    private List list;
    
    public SyncList(List list) {
        this.list = list;
    }
    
    public synchronized void addList(E obj){//僅在這里加上synchronized 
        list.add(obj);
    }
    public List getList() {
        return list;
    }
}

執(zhí)行結(jié)果:

size=200

這個(gè)就是synchronized用在方法上的一個(gè)例子,鎖定的對(duì)象都是同一個(gè)SyncList,所以最終結(jié)果是正確的。因此synchronized使用上很重要的一點(diǎn),是保障多個(gè)線程鎖定的對(duì)象要一致。

異常釋放鎖
public    class Thread1 extends Thread{
    private Object lock;
    public Thread1(Object lock) {
        this.lock=lock;
    }
    public  void  run() {
        try {
            synchronized (lock) {
                for(int i=5;i>-1;i--){
                    System.out.println(Thread.currentThread().getName()+":"+i);
                    Thread.sleep(200);
                    int j= 100/i;
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        for(int i=0;i<2;i++){
            Thread1 t1 = new Thread1(lock);
            t1.start();
            t1.join();
            Thread.sleep(10);
        }
}

執(zhí)行結(jié)果:

Thread-0:5
Thread-0:4
Thread-0:3
Thread-0:2
Thread-0:1
Thread-0:0
Exception in thread "Thread-0" java.lang.ArithmeticException: / by zero
    at Thread1.run(Thread1.java:12)
Thread-1:5
Thread-1:4
Thread-1:3
Thread-1:2
Thread-1:1
Thread-1:0
Exception in thread "Thread-1" java.lang.ArithmeticException: / by zero
    at Thread1.run(Thread1.java:12)

可以看到由于Thread-0先獲取鎖,Thread-1一直處于等待狀態(tài),Thread-0一直執(zhí)行到i=0時(shí),程序發(fā)生異常,鎖被釋放。Thread-1就獲得了鎖開始執(zhí)行。

總結(jié)

1.synchronized可以修飾方法或者代碼塊。
2.盡量使用代碼塊以及減少代碼塊的范圍,有利于提高程序運(yùn)行效率。
3.要注意鎖定的對(duì)象是否一致。

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

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

相關(guān)文章

  • @Java | Thread & synchronized - [ 線程同步鎖 基本使用]

    摘要:線程同步方法是通過(guò)鎖來(lái)實(shí)現(xiàn),每個(gè)對(duì)象都有切僅有一個(gè)鎖,這個(gè)鎖與一個(gè)特定的對(duì)象關(guān)聯(lián),線程一旦獲取了對(duì)象鎖,其他訪問(wèn)該對(duì)象的線程就無(wú)法再訪問(wèn)該對(duì)象的其他非同步方法對(duì)于靜態(tài)同步方法,鎖是針對(duì)這個(gè)類的,鎖對(duì)象是該類的對(duì)象。 對(duì)實(shí)現(xiàn)了Runnable或者Callable接口類,可以通過(guò)多線程執(zhí)行同一實(shí)例的run或call方法,那么對(duì)于同一實(shí)例中的局部變量(非方法變量)就會(huì)有多個(gè)線程進(jìn)行更改或讀取...

    Michael_Lin 評(píng)論0 收藏0
  • Java 線程核心技術(shù)梳理(附源碼)

    摘要:本文對(duì)多線程基礎(chǔ)知識(shí)進(jìn)行梳理,主要包括多線程的基本使用,對(duì)象及變量的并發(fā)訪問(wèn),線程間通信,的使用,定時(shí)器,單例模式,以及線程狀態(tài)與線程組。源碼采用構(gòu)建,多線程這部分源碼位于模塊中。通知可能等待該對(duì)象的對(duì)象鎖的其他線程。 本文對(duì)多線程基礎(chǔ)知識(shí)進(jìn)行梳理,主要包括多線程的基本使用,對(duì)象及變量的并發(fā)訪問(wèn),線程間通信,lock的使用,定時(shí)器,單例模式,以及線程狀態(tài)與線程組。 寫在前面 花了一周時(shí)...

    Winer 評(píng)論0 收藏0
  • java線程synchronized

    摘要:非靜態(tài)方法以及方法內(nèi)部的代碼塊持有的是同一個(gè)對(duì)象鎖,它們是同步執(zhí)行的??芍厝腈i使用時(shí),當(dāng)一個(gè)線程請(qǐng)求一個(gè)對(duì)象鎖時(shí),再次請(qǐng)求該鎖是可以立即得到的。出現(xiàn)異常,會(huì)自動(dòng)釋放鎖同步方法與同步代碼塊作用于整個(gè)方法,可能引起方法執(zhí)行效率下降。 synchronize可以在多個(gè)線程操作同一個(gè)成員變量或者方法時(shí),實(shí)現(xiàn)同步(或者互斥)的效果。synchronized可以作用于方法,以及方法內(nèi)部的代碼塊。 ...

    entner 評(píng)論0 收藏0
  • BATJ都愛問(wèn)線程面試題

    摘要:今天給大家總結(jié)一下,面試中出鏡率很高的幾個(gè)多線程面試題,希望對(duì)大家學(xué)習(xí)和面試都能有所幫助。指令重排在單線程環(huán)境下不會(huì)出先問(wèn)題,但是在多線程環(huán)境下會(huì)導(dǎo)致一個(gè)線程獲得還沒(méi)有初始化的實(shí)例。使用可以禁止的指令重排,保證在多線程環(huán)境下也能正常運(yùn)行。 下面最近發(fā)的一些并發(fā)編程的文章匯總,通過(guò)閱讀這些文章大家再看大廠面試中的并發(fā)編程問(wèn)題就沒(méi)有那么頭疼了。今天給大家總結(jié)一下,面試中出鏡率很高的幾個(gè)多線...

    高勝山 評(píng)論0 收藏0
  • 線程中那些看不見陷阱

    摘要:多線程編程就像一個(gè)沼澤,中間遍布各種各樣的陷阱。但是在多線程編程或者說(shuō)是并發(fā)編程中,有非常多的陷阱被埋在底層細(xì)節(jié)當(dāng)中。線程池類中用于控制線程池狀態(tài)和線程數(shù)的控制變量就是一個(gè)類型的字段。 多線程編程就像一個(gè)沼澤,中間遍布各種各樣的陷阱。大多數(shù)開發(fā)者絕大部分時(shí)間都是在做上層應(yīng)用的開發(fā),并不需要過(guò)多地涉入底層細(xì)節(jié)。但是在多線程編程或者說(shuō)是并發(fā)編程中,有非常多的陷阱被埋在底層細(xì)節(jié)當(dāng)中。如果不知...

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

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

0條評(píng)論

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