簡體   English   中英

Java ConcurrentHashMap初始化

[英]Java ConcurrentHashMap initialization

我目前正在通讀 jdk1.8 中 ConcurrentHashMap 的源代碼,發現initalTable()方法有點混亂。

public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
    implements ConcurrentMap<K,V>, Serializable {
//some fields revolved in this method
transient volatile Node<K,V>[] table;
private transient volatile int sizeCtl;

  private final Node<K,V>[] initTable() {
        Node<K,V>[] tab; int sc;
        while ((tab = table) == null || tab.length == 0) {
            if ((sc = sizeCtl) < 0)
                Thread.yield(); // lost initialization race; just spin
            else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
                try {
                    if ((tab = table) == null || tab.length == 0) {
                        int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
                        @SuppressWarnings("unchecked")
                        Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];//place 1
                        table = tab = nt;//place 2
                        sc = n - (n >>> 2);
                    }
                } finally {
                    sizeCtl = sc;
                }
                break;
            }
        }
        return tab;
    }
}

所以主要的困惑主要集中在以下幾點:

  1. 為什么我們需要while((tab = table) == null || tab.length == 0)來檢查兩個table不是 null 並且它的長度不是 0 並確定是否繼續循環,所以只有當兩者都退出兩個條件為假。 我只是想不出table不是 null 但長度為 0 的情況,因為它是在else if塊中初始化的,其中 n 總是被賦予大於 0 的值。那么為什么我們需要兩者而不是只有一個?

2.第二個問題不是問題,我只是想檢查一下我的假設是否有意義。 因此,想象兩個線程隨后以非常接近的方式運行。 后面的線程可以進入else if塊,如果前面的線程沒有到達table或 place 2 的初始化點,也沒有更新sizeCtl ,那么第二個線程將能夠進入else if塊,所以table字段將再次初始化? 這種情況會在極少數情況下發生嗎? 我知道這不會影響程序的正確性,但在某些情況下會發生嗎?

希望任何人都可以給我一個澄清。 提前致謝。


更新:我忘記了一個成功的 CAS 操作會將sizeCtl交換為 -1 的事實,這將阻止其他線程進入else if塊,但我仍然不清楚為什么我們在ifwhile中需要兩個條件。

單獨分析方法initTable是不夠的。 您需要考慮其他也可以修改tablesizeCtl字段的方法。 在那里你會注意到,例如transfer使用 CAS 將sizeCtl一。 我不確定這是否會導致table.length == 0在任何時間點,但請注意,整個過程要復雜得多,並且initTable可以與 resize 操作同時調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM