Java HashMap竞争条件

我试图找出这段代码中是否存在任何竞争条件.如果密钥不是’Thread.currentThread’那么我会认为是的.但由于线程本身是关键,如何才能有竞争条件?没有其他线程可以在HashMap中更新相同的密钥!

public class SessionTracker {

     static private final Map<Thread,Session>  threadSessionMap = new HashMap<Thread,Session>();

     static public Session get() {
         return threadSessionMap.get(Thread.currentThread());
     }

     static public void set(Session s) {
         threadSessionMap.put(Thread.currentThread(),s);
     }

     static public void reset() {
         threadSessionMap.remove(Thread.currentThread());
     }
}
答案是肯定的,有潜在的竞争条件:

>同时通过两个线程调整HashMap的大小
>碰撞发生时.当两个元素映射到同一个单元格时即使它们具有不同的哈希码,也会发生冲突.在冲突解决期间,可能存在竞争条件,并且一个添加的键/值对可以被另一个线程插入的另一对覆盖.

为了更好地解释我在第二点上的意思,我正在看source code of HashMap in OpenJdk 7

389        int hash = hash(key.hashCode());
390        int i = indexFor(hash, table.length);

首先,它计算密钥的哈希值(组合两个哈希函数),然后映射到具有indexFor的单元格,然后检查该单元格是否包含相同的密钥或已被另一个密钥占用.如果它是相同的键,它只是覆盖该值,这里没有问题.

如果它被占用,它会查看下一个单元格,然后查看下一个单元格直到它找到一个空位置并调用addEntry(),如果数组比某个loadFactor更多,它甚至可以决定调整数组的大小.

我们包含条目的表只是Entry的一个向量,它包含键和值.

146    /**
147     * The table, resized as necessary. Length MUST Always be a power of two.
148     */
149    transient Entry[] table;

在并发环境中,可能发生所有类型的恶意事件,例如,一个线程获得第5个单元格的冲突并查找下一个单元格(6)并将其查找为空.

同时另一个线程由于indexFor而获得索引6,并且两者都决定同时使用该单元格,其中一个重写另一个.

相关文章
相关标签/搜索