第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何證明類 ListHelper<E> 不是線程安全的

如何證明類 ListHelper<E> 不是線程安全的

湖上湖 2021-06-08 13:12:46
最近在看《Java Concurrency in Practice 2nd》一書,作者提到如果我們使用Collections.synchronizedList來創(chuàng)建一個安全線程List,那么我們必須確保我們使用的是同一個鎖,它是來自SynchronizedCollection的一個Object。下面的代碼來自書中:public class ListHelper <E> {    public List<E> list = Collections.synchronizedList(new ArrayList<E>());    public synchronized boolean putIfAbsent(E x) {        boolean absent = !list.contains(x);        if (absent)            list.add(x);        return absent;    }}在這個類中,方法putIfAbsent已經(jīng)被ListHelper中的一個Object鎖住了,但是list.contains并沒有使用這個Object作為鎖,有兩個鎖,所以在多線程下是不安全的。但我的問題是如何證明它不是線程安全的。你有什么想法?
查看完整描述

2 回答

?
隔江千里

TA貢獻1906條經(jīng)驗 獲得超10個贊

以下代碼證明您的類不是線程安全的。

它在兩個不同的線程中將 100000 個數(shù)字添加到列表中:

  • t1使用putIfAbsent你的類的方法

  • t2使用synchronized塊正確鎖定synchronizedList用于控制訪問的相同“互斥”對象,即包裝器列表本身。

由于兩種方法都試圖添加相同的100000 個對象,結(jié)果應(yīng)該是 100000 個對象的列表,即代碼應(yīng)該100000在最后打印。

有時它確實如此,當(dāng)我運行它時,但大多數(shù)時候它比那個高一點,例如100075,從而證明您putIfAbsent的不是線程安全的。

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;


public class Test {

    public static void main(String[] args) throws Exception {

        ListHelper<Integer> helper = new ListHelper<>();

        Thread t1 = new Thread(() -> Test.t1(helper));

        Thread t2 = new Thread(() -> Test.t2(helper));

        t1.start();

        t2.start();

        t1.join();

        t2.join();

        System.out.println(helper.list.size());

    }

    private static void t1(ListHelper<Integer> helper) {

        for (int i = 0; i < 100000; i++)

            helper.putIfAbsent(i);

    }

    private static void t2(ListHelper<Integer> helper) {

        for (int i = 0; i < 100000; i++)

            synchronized (helper.list) { // correct way to synchronize

                if (! helper.list.contains(i))

                    helper.list.add(i);

            }

    }

}

class ListHelper <E> {

    public List<E> list = Collections.synchronizedList(new ArrayList<E>());

    public synchronized boolean putIfAbsent(E x) {

        boolean absent = ! list.contains(x);

        if (absent)

            list.add(x);

        return absent;

    }

}


查看完整回答
反對 回復(fù) 2021-06-17
?
Cats萌萌

TA貢獻1805條經(jīng)驗 獲得超9個贊

通過確保在操作之間運行第二個線程,您可以表明您添加的第一個元素可能存在問題。


import java.util.ArrayList;

import java.util.Collections;

import java.util.List;


public class ListHelper<E> {

    public final List<E> list = Collections.synchronizedList(new ArrayList<E>());


    public synchronized boolean putIfAbsent(E x) {

        boolean absent = !list.contains(x);

        runInANotherThread(() -> list.add(x));

        if (absent)

            list.add(x);

        return absent;

    }


    public static void runInANotherThread(Runnable run) {

        Thread t = new Thread(run);

        t.start();

        try {

            t.join(1000);

        } catch (InterruptedException ignored) {

        }

    }


    public static void main(String[] args) {

        ListHelper<Integer> list = new ListHelper<>();

        list.putIfAbsent(1);

        System.out.println(list.list);

    }

}

印刷


[1, 1]


查看完整回答
反對 回復(fù) 2021-06-17
  • 2 回答
  • 0 關(guān)注
  • 151 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號