日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

 

HashMap線程不安全體現(xiàn)在哪里?如果你到現(xiàn)在還不清楚趕緊看下去,明明白白補(bǔ)一補(bǔ)~。

在JAVA中,HashMap是一種常用的數(shù)據(jù)結(jié)構(gòu),它以鍵值對(duì)的形式存儲(chǔ)和管理數(shù)據(jù)。然而,由于HashMap在多線程環(huán)境下存在線程安全問(wèn)題,因此在使用時(shí)需要格外小心。

簡(jiǎn)單來(lái)說(shuō):在 hashMap1.7 中擴(kuò)容的時(shí)候,因?yàn)椴捎玫氖穷^插法,所以會(huì)可能會(huì)有循環(huán)鏈表產(chǎn)生,導(dǎo)致數(shù)據(jù)有問(wèn)題,在 1.8 版本已修復(fù),改為了尾插法; 在任意版本的 hashMap 中,如果在插入數(shù)據(jù)時(shí)多個(gè)線程命中了同一個(gè)槽,可能會(huì)有數(shù)據(jù)覆蓋的情況發(fā)生,導(dǎo)致線程不安全。

HashMap的線程不安全主要體現(xiàn)在以下兩個(gè)方面:

1. 并發(fā)修改導(dǎo)致數(shù)據(jù)不一致

HashMap的數(shù)據(jù)結(jié)構(gòu)是基于數(shù)組和鏈表實(shí)現(xiàn)的。在進(jìn)行插入或刪除操作時(shí),如果不同線程同時(shí)修改同一個(gè)位置的元素,就會(huì)導(dǎo)致數(shù)據(jù)不一致的情況。具體來(lái)說(shuō),當(dāng)兩個(gè)線程同時(shí)進(jìn)行插入操作時(shí),假設(shè)它們都要插入到同一個(gè)數(shù)組位置,并且該位置沒(méi)有元素,那么它們都會(huì)認(rèn)為該位置可以插入元素,最終就會(huì)導(dǎo)致其中一個(gè)線程的元素被覆蓋掉。此外,在進(jìn)行刪除操作時(shí),如果兩個(gè)線程同時(shí)刪除同一個(gè)元素,也會(huì)導(dǎo)致數(shù)據(jù)不一致的情況。

以下是一個(gè)示例代碼,展現(xiàn)了兩個(gè)線程對(duì)HashMap進(jìn)行并發(fā)修改的情況:

import java.util.HashMap;

public class HashMapThreadUnsafeExample {

    public static void mAIn(String[] args) throws InterruptedException {
        final HashMap<String, Integer> map = new HashMap<>();

        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                map.put("key" + i, i);
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                map.put("key" + i, i * 2);
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("map size: " + map.size());
    }
}
復(fù)制代碼

上述示例代碼中,t1線程和t2線程都向HashMap中插入數(shù)據(jù),由于它們?cè)谶M(jìn)行插入操作時(shí)修改的是同一個(gè)位置的元素,因此最終導(dǎo)致了部分?jǐn)?shù)據(jù)不一致的情況。例如,當(dāng)t1線程插入了(key1, 1)以后,t2線程又插入了(key1, 2),這就導(dǎo)致了(key1, 1)被覆蓋掉,最終HashMap的大小只有10000而不是20000。

2. 并發(fā)擴(kuò)容導(dǎo)致死循環(huán)或數(shù)據(jù)丟失

當(dāng)HashMap的元素?cái)?shù)量達(dá)到一定閾值時(shí),它會(huì)觸發(fā)擴(kuò)容操作,即重新分配更大的數(shù)組并將原來(lái)的元素重新映射到新的數(shù)組上。然而,在進(jìn)行擴(kuò)容操作時(shí),如果不加鎖或者加鎖不正確,就可能導(dǎo)致死循環(huán)或者數(shù)據(jù)丟失的情況。具體來(lái)說(shuō),當(dāng)兩個(gè)線程同時(shí)進(jìn)行擴(kuò)容操作時(shí),它們可能會(huì)同時(shí)將某個(gè)元素映射到新的數(shù)組上,從而導(dǎo)致該元素被覆蓋掉。此外,在進(jìn)行擴(kuò)容操作時(shí),如果線程不安全地修改了next指針,就可能會(huì)導(dǎo)致死循環(huán)的情況。

以下是一個(gè)示例代碼,展現(xiàn)了兩個(gè)線程對(duì)HashMap進(jìn)行并發(fā)擴(kuò)容的情況:

import java.util.HashMap;

public class HashMapThreadUnsafeExample {

    public static void main(String[] args) throws InterruptedException {
        final HashMap<String, Integer> map = new HashMap<>(2, 0.75f);

        map.put("key1", 1);
        map.put("key2", 2);
        map.put("key3", 3);

        Thread t1 = new Thread(() -> {
            for (int i = 4; i < 10000; i++) {
                map.put("key" + i, i);
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 4; i < 10000; i++) {
                map.put("key" + i, i * 2);
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("map size: " + map.size());
    }
}
復(fù)制代碼

上述示例代碼中,t1線程和t2線程都向HashMap中插入數(shù)據(jù),并且HashMap被初始化為大小為2,負(fù)載因子為0.75,這就意味著HashMap在元素?cái)?shù)量達(dá)到3時(shí)就會(huì)進(jìn)行擴(kuò)容操作。由于t1和t2線程同時(shí)進(jìn)行擴(kuò)容操作,它們有可能都將某個(gè)元素映射到新的數(shù)組上,導(dǎo)致該元素被覆蓋掉。此外,在進(jìn)行擴(kuò)容操作時(shí),如果線程不安全地修改了next指針,就可能會(huì)導(dǎo)致死循環(huán)的情況。

除了并發(fā)修改和并發(fā)擴(kuò)容外,還有以下情況可能導(dǎo)致HashMap不安全:

3. 非線程安全的迭代器

當(dāng)使用非線程安全的迭代器遍歷HashMap時(shí),如果在遍歷的過(guò)程中其他線程修改了HashMap的結(jié)構(gòu),就可能拋出
ConcurrentModificationException異常。

以下是一個(gè)示例代碼,展現(xiàn)了如何通過(guò)多線程遍歷HashMap以及導(dǎo)致線程不安全的情況:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class HashMapThreadUnsafeExample {

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

        for (int i = 0; i < 10000; i++) {
            map.put("key" + i, i);
        }

        Thread t1 = new Thread(() -> {
            Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
            while (iterator.hasNext()) {
                System.out.println(iterator.next().getValue());
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 10000; i < 20000; i++) {
                map.put("key" + i, i);
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();
    }
}
復(fù)制代碼

上述示例代碼中,t1線程遍歷了HashMap中的元素,但并沒(méi)有對(duì)其進(jìn)行加鎖保護(hù)。同時(shí),在t1線程遍歷的過(guò)程中,t2線程又進(jìn)行了另外一部分元素的插入操作,這就導(dǎo)致了HashMap結(jié)構(gòu)的不穩(wěn)定性,最終可能會(huì)拋出
ConcurrentModificationException異常。

4. 非線程安全的比較器

當(dāng)使用非線程安全的比較器來(lái)定義HashMap的排序規(guī)則時(shí),就可能導(dǎo)致在并發(fā)環(huán)境下出現(xiàn)數(shù)據(jù)不一致性的情況。

以下是一個(gè)示例代碼,展現(xiàn)了如何通過(guò)多線程修改HashMap中元素順序以及導(dǎo)致線程不安全的情況:

import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

public class HashMapThreadUnsafeExample {

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

        map.put("key1", 1);
        map.put("key2", 2);
        map.put("key3", 3);

        Comparator<String> comparator = (s1, s2) -> {
            int i1 = Integer.parseInt(s1.substring(3));
            int i2 = Integer.parseInt(s2.substring(3));
            return Integer.compare(i1, i2);
        };

        Thread t1 = new Thread(() -> {
            for (int i = 4; i < 10000; i++) {
                map.put("key" + i, i);
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 4; i < 10000; i++) {
                map.put("key" + i, i * 2);
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("map: " + map);
    }
}
復(fù)制代碼

上述示例代碼中,HashMap的排序規(guī)則使用了一個(gè)基于字符串處理的比較器來(lái)定義。當(dāng)t1線程和t2線程同時(shí)進(jìn)行插入操作時(shí),由于它們?cè)诓煌脑厣蠄?zhí)行修改操作,因此并不會(huì)出現(xiàn)
ConcurrentModificationException異常。然而,由于比較器不是線程安全的,當(dāng)t1和t2線程同時(shí)進(jìn)行對(duì)相同的元素值進(jìn)行賦值操作時(shí),就可能導(dǎo)致HashMap結(jié)構(gòu)的不穩(wěn)定性。例如,當(dāng)t1線程將"key5"的值修改為5時(shí),t2線程可能只修改到"value"字段的一部分,因此最終HashMap中的值可能出現(xiàn)混亂的情況。

寫(xiě)到這里我想告訴大家:HashMap在多線程環(huán)境下存在線程安全問(wèn)題,具體表現(xiàn)為并發(fā)修改導(dǎo)致數(shù)據(jù)不一致和并發(fā)擴(kuò)容導(dǎo)致死循環(huán)或數(shù)據(jù)丟失。因此,在使用HashMap時(shí)需要采取相應(yīng)的線程安全措施,例如使用ConcurrentHashMap、加鎖等。

分享到:
標(biāo)簽:HashMap
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定