
|
If you were logged in you would be able to see more operations.
|
|
|
|
DynamicCollection.remove and DynamicCollection$DynamicIterator.hasNext() are deadlock prone. I expect this might be the case for some more interleaving code paths.
public boolean hasNext() {
synchronized (iteratorsLock) {
hasNext = (cursor < storage.size() ? Boolean.TRUE : Boolean.FALSE);
}
return hasNext.booleanValue();
}
public boolean remove(Object o) {
synchronized (storage) {
int index = storage.indexOf(o);
if (index == -1)
return false;
remove(index);
return true;
}
}
hasNext() is acquiring the monitor for iteratorsLock and then storage (since storage is a Collections.synchronizedList which by default using the collection's own monitor). remove() acquires storage and then iteratorsLock (via the call to remove(int)).
A point to be wary of - using a Collections.synchronizedList (or any class that 'supports' a client locking protocol) and then locking on it also. This leads to acquire ordering that is not apparent.
The solution to this is to enforce an acquistion order. So if you are going to call a method on storage while holding iteratorsLock, you'll want to acquire the storage lock *before* acquiring iteratorsLock. Of course, this assumes that you are expecting that operations on storage lock on 'this'.
|
|
Description
|
DynamicCollection.remove and DynamicCollection$DynamicIterator.hasNext() are deadlock prone. I expect this might be the case for some more interleaving code paths.
public boolean hasNext() {
synchronized (iteratorsLock) {
hasNext = (cursor < storage.size() ? Boolean.TRUE : Boolean.FALSE);
}
return hasNext.booleanValue();
}
public boolean remove(Object o) {
synchronized (storage) {
int index = storage.indexOf(o);
if (index == -1)
return false;
remove(index);
return true;
}
}
hasNext() is acquiring the monitor for iteratorsLock and then storage (since storage is a Collections.synchronizedList which by default using the collection's own monitor). remove() acquires storage and then iteratorsLock (via the call to remove(int)).
A point to be wary of - using a Collections.synchronizedList (or any class that 'supports' a client locking protocol) and then locking on it also. This leads to acquire ordering that is not apparent.
The solution to this is to enforce an acquistion order. So if you are going to call a method on storage while holding iteratorsLock, you'll want to acquire the storage lock *before* acquiring iteratorsLock. Of course, this assumes that you are expecting that operations on storage lock on 'this'. |
Show » |
|