Jav*_*ner 6 java multithreading synchronization race-condition
我试图找出这段代码中是否存在任何竞争条件.如果密钥不是'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());
}
}
Run Code Online (Sandbox Code Playgroud)
sti*_*vlo 13
答案是肯定的,有潜在的竞争条件:
为了更好地解释我在第二点上的意思,我在OpenJdk 7中查看了HashMap的源代码
389 int hash = hash(key.hashCode());
390 int i = indexFor(hash, table.length);
Run Code Online (Sandbox Code Playgroud)
首先,它计算密钥的哈希值(组合两个哈希函数),然后映射到一个单元格indexFor,然后检查该单元格是否包含相同的密钥或已被另一个密钥占用.如果它是相同的键,它只是覆盖该值,这里没有问题.
如果它被占用,它会查看下一个单元格,然后查看下一个单元格,直到它找到一个空位置并调用addEntry(),如果数组的负载超过某个数组,它甚至可以决定调整数组的大小loadFactor.
我们table包含条目只是一个Entry包含键和值的向量.
146 /**
147 * The table, resized as necessary. Length MUST Always be a power of two.
148 */
149 transient Entry[] table;
Run Code Online (Sandbox Code Playgroud)
在并发环境中,可能发生所有类型的恶意事件,例如,一个线程获得第5个单元格的冲突并查找下一个单元格(6)并将其查找为空.
与此同时,另一个线程得到的索引为6,indexFor并且两者都决定同时使用该单元格,其中一个线程覆盖另一个.