最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于java中線程安全問題詳解

 更新時間:2021年11月28日 12:38:58   作者:我想月薪過萬  
最近工作中遇到不少多線程問題,但自己一直對多線程的理解比較表層,所以深入研究了一番,下面這篇文章主要給大家介紹了關(guān)于java中線程安全問題的相關(guān)資料,需要的朋友可以參考下

一、什么時候數(shù)據(jù)在多線程并發(fā)的環(huán)境下會存在安全問題?

三個條件:

  • 條件1:多線程并發(fā)。
  • 條件2:有共享數(shù)據(jù)。
  • 條件3:共享數(shù)據(jù)有修改的行為。

滿足以上3個條件之后,就會存在線程安全問題。

二、怎么解決線程安全問題?

????????線程排隊執(zhí)行。(不能并發(fā))。用排隊執(zhí)行解決線程安全問題。這種機制被稱為:線程同步機制。

三、銀行 取錢/存錢 案例

Account 類

package ThreadSafa;
 
/*
銀行賬戶
 */
 
public class Account {
    // 賬號
    private String actno;
    // 余額
    private double balance;
 
    public Account() {
    }
 
    public Account(String actno, double balance) {
        this.actno = actno;
        this.balance = balance;
    }
 
    public String getActno() {
        return actno;
    }
 
    public void setActno(String actno) {
        this.actno = actno;
    }
 
    public double getBalance() {
        return balance;
    }
 
    public void setBalance(double balance) {
        this.balance = balance;
    }
 
    //取款方法
    public void withdraw(double money) {
        // 取款之前的余額
        double before = this.getBalance();
        // 取款之后的余額
        double after = before - money;
        // 更新余額
        try {
            //模擬網(wǎng)絡延時 更新余額不及時 百分百會出問題
            Thread.sleep(1 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.setBalance(after);
    }
}

AccountThread 類

package ThreadSafa;
 
public class AccountThread extends Thread {
    // 兩個線程必須共享同一個賬戶對象。
    private Account act;
 
    //通過構(gòu)造方法傳遞過來賬戶對象
 
 
    public AccountThread(Account act) {
        this.act = act;
    }
 
    @Override
    public void run() {
        double money = 5000;
        //取款
        act.withdraw(5000);
 
        System.out.println(Thread.currentThread().getName() + "賬戶" + act.getActno() + "取款成功,余額" + act.getBalance());
    }
}

Test 類

package ThreadSafa;
 
public class Test {
    public static void main(String[] args) {
        // 創(chuàng)建賬戶對象
        Account act = new Account("act-001", 10000);
        //創(chuàng)建兩個線程
        Thread t1 = new AccountThread(act);
        Thread t2 = new AccountThread(act);
        //設置name
        t1.setName("t1");
        t2.setName("t2");
        //啟動線程
        t1.start();
        t2.start();
    }
}

?運行問題

?解決方法? 修改?Account 類? 中的?withdraw 方法

package ThreadSafa;
 
/*
銀行賬戶
 */
 
public class Account {
    // 賬號
    private String actno;
    // 余額
    private double balance;
 
    public Account() {
    }
 
    public Account(String actno, double balance) {
        this.actno = actno;
        this.balance = balance;
    }
 
    public String getActno() {
        return actno;
    }
 
    public void setActno(String actno) {
        this.actno = actno;
    }
 
    public double getBalance() {
        return balance;
    }
 
    public void setBalance(double balance) {
        this.balance = balance;
    }
 
    //取款方法
    public void withdraw(double money) {
        // 以下這幾行代碼必須是線程排隊的,不能并發(fā)
        // 一個線程把這里的代碼全部執(zhí)行結(jié)束之后,另外一個線程才能進來
 
        /*
        線程同步機制的語法是:
            synchronized (){
                // 線程同步代碼塊
            }
            synchronized后面小括號中的這個“數(shù)據(jù)”是相當關(guān)鍵的。
            這個數(shù)據(jù)必須是多線程共享的數(shù)據(jù)。才能達到多線程排隊
            ()中寫什么?
                那要看你想讓那些線程同步。
                假設t1、t2、t3、t4、t5,有5個線程,
                你只希望t1 t2 t3排隊,t4 t5 不需要排隊。怎么辦?
                你一定要在()中寫一個t1 t2 t3共享的對象。而這個
                對象對于t4 t5來說不是共享的。
             這里的共享對象是:賬戶對象
             賬戶對象是共享的,那么this就是賬戶對象吧!??!
             不一定是 this ,這里只要是多線程共享的那個對象就行。
         */
 
        synchronized (this) {
            // 取款之前的余額
            double before = this.getBalance();
            // 取款之后的余額
            double after = before - money;
            // 更新余額
            try {
                //模擬網(wǎng)絡延時 更新余額不及時 百分百會出問題
                Thread.sleep(1 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.setBalance(after);
        }
    }
}

為什么會出現(xiàn)線程安全問題

計算機系統(tǒng)資源分配的單位為進程,同一個進程中允許多個線程并發(fā)執(zhí)行,并且多個線程會共享進程范圍內(nèi)的資源:例如內(nèi)存地址。當多個線程并發(fā)訪問同一個內(nèi)存地址并且內(nèi)存地址保存的值是可變的時候可能會發(fā)生線程安全問題,因此需要內(nèi)存數(shù)據(jù)共享機制來保證線程安全問題。

對應到java服務來說,在虛擬中的共享內(nèi)存地址是java的堆內(nèi)存,比如以下程序中線程安全問題:

public class ThreadUnsafeDemo {

    private static final ExecutorService EXECUTOR_SERVICE;

    static {
        EXECUTOR_SERVICE = new ThreadPoolExecutor(100, 100, 1000 * 10,
                TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(100), new ThreadFactory() {

            private AtomicLong atomicLong = new AtomicLong(1);

            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "Thread-Safe-Thread-" + atomicLong.getAndIncrement());
            }
        });
    }


    public static void main(String[] args) throws Exception {
        Map<String, Integer> params = new HashMap<>();

        List<Future> futureList = new ArrayList<>(100);
        for (int i = 0; i < 100; i++) {
            futureList.add(EXECUTOR_SERVICE.submit(new CacheOpTask(params)));
        }

        for (Future future : futureList) {
            System.out.println("Future result:" + future.get());
        }

        System.out.println(params);
    }

    private static class CacheOpTask implements Callable<Integer> {

        private Map<String, Integer> params;

        CacheOpTask(Map<String, Integer> params) {
            this.params = params;
        }

        @Override
        public Integer call() {
            for (int i = 0; i < 100; i++) {
                int count = params.getOrDefault("count", 0);
                params.put("count", ++count);
            }
            return params.get("count");
        }

    }
}

創(chuàng)建100個task,每個task對map中的元素累加100此,程序執(zhí)行結(jié)果為:

{count=9846}

而預期的正確結(jié)果為:

{count=10000}

至于出現(xiàn)這種問題的原因,下面會具體分析。

判斷是否有線程安全性的一個原則是:

是否有多線程訪問可變的共享變量

四、總結(jié)

  • 一個對象一把鎖
  • 線程拿到鎖才能執(zhí)行同步代碼塊代碼

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

相關(guān)文章

  • 詳解Java中字典樹(Trie樹)的圖解與實現(xiàn)

    詳解Java中字典樹(Trie樹)的圖解與實現(xiàn)

    Trie又稱為前綴樹或字典樹,是一種有序樹,它是一種專門用來處理串匹配的數(shù)據(jù)結(jié)構(gòu)。本文將利用圖解詳細講解Trie樹的實現(xiàn),需要的可以參考一下
    2022-05-05
  • 深入理解Java序列化與反序列化

    深入理解Java序列化與反序列化

    今天教大家深入理解Java的序列化與反序列化,文中介紹的非常詳細,有很多代碼示例,對正在學習Java的小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05
  • java開發(fā)中防止重復提交的幾種解決方案

    java開發(fā)中防止重復提交的幾種解決方案

    我們?nèi)粘i_發(fā)中有很多的應用場景都會遇到重復提交問題,下面這篇文章主要給大家介紹了關(guān)于java開發(fā)中防止重復提交的幾種解決方案,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-10-10
  • 詳解java Collections.sort的兩種用法

    詳解java Collections.sort的兩種用法

    這篇文章主要介紹了詳解java Collections.sort的兩種用法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • UrlDecoder和UrlEncoder使用詳解_動力節(jié)點Java學院整理

    UrlDecoder和UrlEncoder使用詳解_動力節(jié)點Java學院整理

    這篇文章主要為大家詳細介紹了UrlDecoder和UrlEncoder使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • org.apache.zookeeper.KeeperException.BadVersionException異常的解決

    org.apache.zookeeper.KeeperException.BadVersionException異常的解

    在使用Apache ZooKeeper進行分布式協(xié)調(diào)時,你可能會遇到org.apache.zookeeper.KeeperException.BadVersionException異常,本文就來介紹一下解決方法,感興趣的可以了解一下
    2024-03-03
  • java selenium教程之selenium詳細介紹

    java selenium教程之selenium詳細介紹

    本文主要介紹Java selenium,這里整理了selenium的一些基本資料,此軟件主要用于Web UI自動測試框架,有興趣的同學可以看一下
    2016-08-08
  • SpringBoot @ConfigurationProperties使用詳解

    SpringBoot @ConfigurationProperties使用詳解

    這篇文章主要介紹了SpringBoot @ConfigurationProperties使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-02-02
  • java 8 lambda表達式中的異常處理操作

    java 8 lambda表達式中的異常處理操作

    這篇文章主要介紹了java 8 lambda表達式中的異常處理操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • springboot中不能獲取post請求參數(shù)的解決方法

    springboot中不能獲取post請求參數(shù)的解決方法

    這篇文章主要介紹了springboot中不能獲取post請求參數(shù)的解決方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-06-06

最新評論

理塘县| 楚雄市| 普格县| 通化县| 丰原市| 札达县| 昂仁县| 盐山县| 田阳县| 庐江县| 张掖市| 阿鲁科尔沁旗| 团风县| 临夏县| 七台河市| 万州区| 宁晋县| 孙吴县| 武胜县| 微山县| 汝南县| 双辽市| 仙桃市| 肇州县| 七台河市| 和顺县| 曲周县| 滨海县| 平凉市| 东山县| 开原市| 彭阳县| 荔波县| 北辰区| 文山县| 寿光市| 武鸣县| 拜泉县| 临泽县| 津南区| 涞水县|