|
精华帖 (0) :: 良好帖 (14) :: 新手帖 (11) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
时间:2008-02-27
cammette 写道 jsyx 写道 cammette 写道 jsyx 写道 cammette 写道 第一种这样会好点
synchronized(key) { value = map.get(key); } 个人认为,这种写法不是线程安全的 为什么呢? 我们操作map时关注的是key对应的value。 只要我们改变某key的value能同步不就可以了吗? 你总要考虑到写的情况吧。 楼主的测试使用的是HashMap。 在java中,hashmap内部是使用数组来实现的。 无论是put还是get,首先都要根据key的hash值以及数组的长度以及一些其他的常数,计算出一个位置,然后对应get/put,会在这个位置内搜寻或者放置value。当map中存入的对象的个数到了一个临界值时(threshold),hashmap会重新初始化一个新的更长的数组,并且会重新分配所有已存的对象。
public V get(Object key) {
Object k = maskNull(key);
int hash = hash(k);
int i = indexFor(hash, table.length);
Entry<K,V> e = table[i];
while (true) {
if (e == null)
return null;
if (e.hash == hash && eq(k, e.key))
return e.value;
e = e.next;
}
}
public V put(K key, V value) {
K k = maskNull(key);
int hash = hash(k);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
if (e.hash == hash && eq(k, e.key)) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, k, value, i);
return null;
}
举例来说: 如果你只同步key,那么当执行到这一行,以后 int i = indexFor(hash, table.length); 另外一个线程执行了一个新的put操作,导致数组被resize,对象被重新放置。 这样的结果就是你的get操作取不出正确的value或者直接返回null
/**
* Rehashes the contents of this map into a new array with a
* larger capacity. This method is called automatically when the
* number of keys in this map reaches its threshold.
*
* If current capacity is MAXIMUM_CAPACITY, this method does not
* resize the map, but sets threshold to Integer.MAX_VALUE.
* This has the effect of preventing future calls.
*
* @param newCapacity the new capacity, MUST be a power of two;
* must be greater than current capacity unless current
* capacity is MAXIMUM_CAPACITY (in which case value
* is irrelevant).
*/
void resize(int newCapacity) {
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
if (oldCapacity == MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return;
}
Entry[] newTable = new Entry[newCapacity];
transfer(newTable);
table = newTable;
threshold = (int)(newCapacity * loadFactor);
}
受教了。 不过lz的 synchronized(anObject) { value = map.get(key); } 也会遇到这个问题 synchronized(anObject) { value = map.get(key); } synchronized(anObject) { map.put(key, value); } 这样,我觉得不会有问题,只要保证put和get都同步到这个anObject上来 synchronized(key) { value = map.get(key); } synchronized(key) { map.put(key, value); } 这样会有问题,因为put和get的key可能是不同的对象 |
|
| 返回顶楼 | |
|
时间:2008-03-05
上面的评论相当的精彩
我请教一下为什么不是
synchronized(map){
value = map.get(key);
}
|
|
| 返回顶楼 | |
|
时间:2008-03-08
jomper 写道 上面的评论相当的精彩 我请教一下为什么不是
synchronized(map){
value = map.get(key);
}其实是一样的, synchronized(anObject) { value = map.get(key); } synchronized(map){ value = map.get(key); } 如果anObject只用在map的get和put的同步中,效果是一样的; |
|
| 返回顶楼 | |
|
时间:2008-04-22
看楼主的图很吓人,synchronized效率这么差啊,jdk1.4的也只能用这个了吧
网上有人建议是说建一个 final static Object lockForMap=new Object(); 然后 synchronized(lockForMap){ value=map.get(key); } 因为synchronized(map)的话,有可能map会被重新实例化,这样子也不保险。 |
|
| 返回顶楼 | |





