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

Java使用線程同步解決線程安全問(wèn)題詳解

 更新時(shí)間:2022年05月07日 11:45:47   作者:遇安.112  
線程安全是多線程編程時(shí)的計(jì)算機(jī)程序代碼中的一個(gè)概念。在擁有共享數(shù)據(jù)的多條線程并行執(zhí)行的程序中,線程安全的代碼會(huì)通過(guò)同步機(jī)制保證各個(gè)線程都可以正常且正確的執(zhí)行,不會(huì)出現(xiàn)數(shù)據(jù)污染等意外情況

第一種方法:同步代碼塊:

作用:把出現(xiàn)線程安全的核心代碼上鎖

原理:每次只能一個(gè)線程進(jìn)入,執(zhí)行完畢后自行解鎖,其他線程才能進(jìn)來(lái)執(zhí)行

鎖對(duì)象要求:理論上,鎖對(duì)象只要對(duì)于當(dāng)前同時(shí)執(zhí)行的線程是同一個(gè)對(duì)象即可

缺點(diǎn):會(huì)干擾其他無(wú)關(guān)線程的執(zhí)行

所以,這種只是理論上的,了解即可,現(xiàn)實(shí)中并不會(huì)這樣用

public class 多線程_4線程同步 {
    public static void main(String[] args) {
        //定義線程類(lèi),創(chuàng)建一個(gè)共享的賬戶(hù)對(duì)象
        account a=new account("abc",10000);
        //創(chuàng)建兩個(gè)取錢(qián)的線程對(duì)象
        new drawthread(a,"小明").start();
        new drawthread(a,"小紅").start();
    }
}
//取錢(qián)的線程類(lèi)
class drawthread extends Thread{
    //接收處理的賬戶(hù)對(duì)象
    private account acc;
    public drawthread(account acc,String name){
        super(name);
        this.acc=acc;
    }
    public void run(){
        //取錢(qián)
        acc.drawmoney(10000);
    }
}
class account{
    private String cartId;
    private double money;//賬戶(hù)余額
    public account() {
    }
    public account(String cartId, double money) {
        this.cartId = cartId;
        this.money = money;
    }
    public String getCartId() {
        return cartId;
    }
    public void setCartId(String cartId) {
        this.cartId = cartId;
    }
    public double getMoney() {
        return money;
    }
    public void setMoney(double money) {
        this.money = money;
    }
    public void drawmoney(double money) {
        //先獲取是誰(shuí)來(lái)取錢(qián),線程名即是人名
        String name=Thread.currentThread().getName();
        //同步代碼塊
        //作用:把出現(xiàn)線程安全的核心代碼上鎖
        //原理:每次只能一個(gè)線程進(jìn)入,執(zhí)行完畢后自行解鎖,其他線程才能進(jìn)來(lái)執(zhí)行
        //鎖對(duì)象要求:理論上,鎖對(duì)象只要對(duì)于當(dāng)前同時(shí)執(zhí)行的線程是同一個(gè)對(duì)象即可
        //缺點(diǎn):會(huì)干擾其他無(wú)關(guān)線程的執(zhí)行
        synchronized ("遇安") {//"鎖名自取,無(wú)意義"
            //判斷賬戶(hù)是否夠錢(qián)
            if(this.money>=money){
                //取錢(qián)
                System.out.println(name+"來(lái)取錢(qián)成功,取了:"+money);
                //更新金額
                this.money-=money;
                System.out.println(name+"取錢(qián)后剩余:"+this.money);
            }else{
                //余額不足
                System.out.println(name+"來(lái)取錢(qián),但余額不足!");
            }
        }
    }
}

規(guī)范上:建議使用共享資源作為鎖對(duì)象

對(duì)于實(shí)例化方法建議使用this作為鎖對(duì)象

對(duì)于靜態(tài)方法,建議使用字節(jié)碼(類(lèi)名.class)對(duì)象作為鎖對(duì)象

        //接上文代碼
//實(shí)例化方法建議使用this作為鎖對(duì)象
synchronized (this) {
            //判斷賬戶(hù)是否夠錢(qián)
            if(this.money>=money){
                //取錢(qián)
                System.out.println(name+"來(lái)取錢(qián)成功,取了:"+money);
                //更新金額
                this.money-=money;
                System.out.println(name+"取錢(qián)后剩余:"+this.money);
            }else{
                //余額不足
                System.out.println(name+"來(lái)取錢(qián),但余額不足!");
            }
        }
//靜態(tài)方法建議使用類(lèi)名.class作為鎖對(duì)象
//每次只有一個(gè)線程能鎖這個(gè)類(lèi),而類(lèi)也是唯一的
  public static void run(){
        synchronized(account.class){
        }
    }

第二種方法:同步方法

    //同步方法
        public synchronized void drawmoney(double money) {
        //先獲取是誰(shuí)來(lái)取錢(qián),線程名即是人名
        String name=Thread.currentThread().getName();
            //判斷賬戶(hù)是否夠錢(qián)
            if(this.money>=money){
                //取錢(qián)
                System.out.println(name+"來(lái)取錢(qián)成功,取了:"+money);
                //更新金額
                this.money-=money;
                System.out.println(name+"取錢(qián)后剩余:"+this.money);
            }else{
                //余額不足
                System.out.println(name+"來(lái)取錢(qián),但余額不足!");
            }
    }

那么同步代碼塊和同步方法哪個(gè)好一點(diǎn)呢?

答案是:同步代碼塊

因?yàn)橥酱a塊鎖的范圍更小一點(diǎn),同步方法鎖的范圍更大一點(diǎn)

但其實(shí)在現(xiàn)實(shí)中同步方法用的更多一點(diǎn),因?yàn)榇a簡(jiǎn)潔好寫(xiě)一點(diǎn),更方便

第三種方法:Lock鎖

JDK5后出現(xiàn),更加靈活方便

Lock是接口不能直接實(shí)例化,我們需要采用它的實(shí)現(xiàn)類(lèi)ReentrantLock來(lái)構(gòu)建Lock鎖對(duì)象

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class 多線程_4線程同步Lock鎖 {
    public static void main(String[] args) {
        //定義線程類(lèi),創(chuàng)建一個(gè)共享的賬戶(hù)對(duì)象
        account a=new account("abc",10000);
        //創(chuàng)建兩個(gè)取錢(qián)的線程對(duì)象
        new drawthread(a,"小明").start();
        new drawthread(a,"小紅").start();
    }
}
//取錢(qián)的線程類(lèi)
class drawthread2 extends Thread{
    //接收處理的賬戶(hù)對(duì)象
    private account acc;
    public drawthread2(account acc,String name){
        super(name);
        this.acc=acc;
    }
    public void run(){
        //取錢(qián)
        acc.drawmoney(10000);
    }
}
class account2{
    private String cartId;
    private double money;//賬戶(hù)余額
    //final修飾后:鎖對(duì)象是唯一的和不可替換的
//Lock是接口不能直接實(shí)例化,我們需要采用它的實(shí)現(xiàn)類(lèi)ReentrantLock來(lái)構(gòu)建Lock鎖對(duì)象
    private final Lock lock=new ReentrantLock();
    public account2() {
    }
    public account2(String cartId, double money) {
        this.cartId = cartId;
        this.money = money;
    }
    public String getCartId() {
        return cartId;
    }
    public void setCartId(String cartId) {
        this.cartId = cartId;
    }
    public double getMoney() {
        return money;
    }
    public void setMoney(double money) {
        this.money = money;
    }
    public void drawmoney(double money) {
        //先獲取是誰(shuí)來(lái)取錢(qián),線程名即是人名
        String name=Thread.currentThread().getName();
        lock.lock();//上鎖
        //判斷賬戶(hù)是否夠錢(qián)
        try {
            if(this.money>=money){
                //取錢(qián)
                System.out.println(name+"來(lái)取錢(qián)成功,取了:"+money);
                //更新金額
                this.money-=money;
                System.out.println(name+"取錢(qián)后剩余:"+this.money);
            }else{
                //余額不足
                System.out.println(name+"來(lái)取錢(qián),但余額不足!");
            }
            //防止代碼出現(xiàn)bug而不能解鎖
        } finally {
            lock.unlock();//解鎖
        }
    }
}

到此這篇關(guān)于Java使用線程同步解決線程安全問(wèn)題詳解的文章就介紹到這了,更多相關(guān)Java線程同步內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺談javaSE GUI (Action事件)

    淺談javaSE GUI (Action事件)

    下面小編就為大家?guī)?lái)一篇淺談javaSE GUI (Action事件)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-06-06
  • SpringBoot3.2.2整合MyBatis Plus3.5.5的詳細(xì)過(guò)程

    SpringBoot3.2.2整合MyBatis Plus3.5.5的詳細(xì)過(guò)程

    這篇文章給大家介紹了SpringBoot3.2.2整合MyBatis Plus3.5.5的詳細(xì)過(guò)程,文中通過(guò)代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-01-01
  • Java中的ConcurrentLinkedQueue松散隊(duì)列解析

    Java中的ConcurrentLinkedQueue松散隊(duì)列解析

    這篇文章主要介紹了Java中的ConcurrentLinkedQueue松散隊(duì)列解析,鏈表是松散的,鏈表節(jié)點(diǎn)并不都是有效的,允許存在無(wú)效節(jié)點(diǎn)val=null,但是只有最后一個(gè)節(jié)點(diǎn)才能next=null,需要的朋友可以參考下
    2023-12-12
  • idea快速搭建spring cloud注冊(cè)中心與注冊(cè)的方法

    idea快速搭建spring cloud注冊(cè)中心與注冊(cè)的方法

    這篇文章主要介紹了idea快速搭建spring cloud注冊(cè)中心與注冊(cè)的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • 淺析SpringBoot及環(huán)境搭建過(guò)程

    淺析SpringBoot及環(huán)境搭建過(guò)程

    Spring Boot是由Pivotal團(tuán)隊(duì)提供的全新框架,其設(shè)計(jì)目的是用來(lái)簡(jiǎn)化新Spring應(yīng)用的初始搭建以及開(kāi)發(fā)過(guò)程.這篇文章主要介紹了SpringBoot介紹及環(huán)境搭建,需要的朋友可以參考下
    2018-01-01
  • IntelliJ IDEA設(shè)置Tabs實(shí)現(xiàn)同時(shí)打開(kāi)多個(gè)文件且分行顯示

    IntelliJ IDEA設(shè)置Tabs實(shí)現(xiàn)同時(shí)打開(kāi)多個(gè)文件且分行顯示

    今天小編就為大家分享一篇關(guān)于IntelliJ IDEA設(shè)置Tabs實(shí)現(xiàn)同時(shí)打開(kāi)多個(gè)文件且分行顯示,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-10-10
  • 深入理解Spring MVC概要與環(huán)境配置

    深入理解Spring MVC概要與環(huán)境配置

    本篇文章主要介紹了深入理解Spring MVC概要與環(huán)境配置 ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-03-03
  • Java創(chuàng)建對(duì)象(顯式創(chuàng)建和隱含創(chuàng)建)

    Java創(chuàng)建對(duì)象(顯式創(chuàng)建和隱含創(chuàng)建)

    本文詳細(xì)介紹對(duì)象的創(chuàng)建,在 Java 語(yǔ)言中創(chuàng)建對(duì)象分顯式創(chuàng)建與隱含創(chuàng)建兩種情況,顯式創(chuàng)建和隱含創(chuàng)建,,需要的朋友可以參考下面文章的具體內(nèi)容
    2021-09-09
  • Java中Semaphore(信號(hào)量)的使用方法

    Java中Semaphore(信號(hào)量)的使用方法

    這篇文章主要介紹了Java中Semaphore(信號(hào)量)的使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • MyBatis字段名和屬性名不一致的解決方法

    MyBatis字段名和屬性名不一致的解決方法

    本文主要介紹了MyBatis字段名和屬性名不一致的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01

最新評(píng)論