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

Java使用線程同步解決線程安全問題詳解

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

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

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

原理:每次只能一個線程進入,執(zhí)行完畢后自行解鎖,其他線程才能進來執(zhí)行

鎖對象要求:理論上,鎖對象只要對于當前同時執(zhí)行的線程是同一個對象即可

缺點:會干擾其他無關線程的執(zhí)行

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

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

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

對于實例化方法建議使用this作為鎖對象

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

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

第二種方法:同步方法

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

那么同步代碼塊和同步方法哪個好一點呢?

答案是:同步代碼塊

因為同步代碼塊鎖的范圍更小一點,同步方法鎖的范圍更大一點

但其實在現(xiàn)實中同步方法用的更多一點,因為代碼簡潔好寫一點,更方便

第三種方法:Lock鎖

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

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

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

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

相關文章

  • 淺談javaSE GUI (Action事件)

    淺談javaSE GUI (Action事件)

    下面小編就為大家?guī)硪黄獪\談javaSE GUI (Action事件)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06
  • SpringBoot3.2.2整合MyBatis Plus3.5.5的詳細過程

    SpringBoot3.2.2整合MyBatis Plus3.5.5的詳細過程

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

    Java中的ConcurrentLinkedQueue松散隊列解析

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

    idea快速搭建spring cloud注冊中心與注冊的方法

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

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

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

    IntelliJ IDEA設置Tabs實現(xiàn)同時打開多個文件且分行顯示

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

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

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

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

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

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

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

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

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

最新評論