-
Bug
-
Resolution: Won't Fix
-
P4
-
None
-
6
-
generic
-
generic
Current AbstractDocument locking implementation has a number of problems:
1. Java memory model related
see jsr 133 and JLS chapter 17
Consider use case:
Thread 1 Thread 2
writeLock readLock
mutateDocument readDocument
writeUnlock readUnLock
One would think mutateDocument and readDocument can not happen
simultaneously because of write/read locks.
Unfortunately it is not the case for current implementation.
From jsr133
Happens-Before Relationship Two actions can be ordered by a
happens-before relationship. If one action happens-before another,
then the first is visible to and ordered before the second. It should
be stressed that a happens-before relationship between two actions
does not imply that those actions must occur in that order in a Java
platform implementation. The happens-before relation mostly stresses
orderings between two actions that conflict with each other, and
defines when data races take place. There are a number of ways to
induce a happens-before ordering, including:
* Each action in a thread happens-before every subsequent action in that thread.
* An unlock on a monitor happens-before every subsequent lock on that monitor.
* A write to a volatile field happens-before every subsequent read of that volatile.
* A call to start() on a thread happens-before any actions in the started thread.
* All actions in a thread happen-before any other thread successfully returns from a join() on
that thread.
* If an action a happens-before an action b, and b happens before an action c, then a happensbefore c.
For described example we have following guarantees:
- writeLock happens before writeUnLock (they lock the same monitor)
- readLock happens before readUnLock (they lock the same monitor)
- readLock and writeLock are mutually exclusive (they implemented this way)
Execution order then would be writeLock writeUnlock, readLock readUnlock
or readLock readUnlock, writeLock writeUnlock
There is no guarantee when mutateDocument and readDocument happen.
JVM could execute the use case is this way:
Thread 1 Thread 2
mutateDocument readDocument
writeLock
writeUnlock
readLock
readUnlock
The same could happen for two threads mutating the document.
That leads to document model corruption.
(Swing in general does not pay attention to java memory model. The bug
on this will be opened shortly)
2. getting readLock while having writeLock does nothing assuming that
having write lock grants read permission. It might lead to some unexpected problems.
Consider use case:
writeLock
readLock
writeUnlock
doSomething
readUnlock
doSomething will be executed without readLock.
readUnlock will throw StateInvariantError(BAD_LOCK_STATE) becuase
there are no readers registered.
3. readUnlock does not check whether the current thread has acquired readLock.
It might lead to some hard to debug problems.
4. writeUnlock does not check whether the current thread is write lock owner. It
might lead to document model corruptions which is hard to debug.
To address all these issues I suggest to use java.util.concurrent.locks.ReentrantReadWriteLock
ReentrantReadWriteLock was designed exactly for the functionality we are looking for.
Most importantly it addresses the first issue (JMM problem)
From java doc for ReentrantLock
----
A reentrant mutual exclusion Lock with the same basic behavior and
semantics as the implicit monitor lock accessed using synchronized
methods and statements, but with extended capabilities.
----
###@###.### 2004-12-17 01:25:18 GMT
1. Java memory model related
see jsr 133 and JLS chapter 17
Consider use case:
Thread 1 Thread 2
writeLock readLock
mutateDocument readDocument
writeUnlock readUnLock
One would think mutateDocument and readDocument can not happen
simultaneously because of write/read locks.
Unfortunately it is not the case for current implementation.
From jsr133
Happens-Before Relationship Two actions can be ordered by a
happens-before relationship. If one action happens-before another,
then the first is visible to and ordered before the second. It should
be stressed that a happens-before relationship between two actions
does not imply that those actions must occur in that order in a Java
platform implementation. The happens-before relation mostly stresses
orderings between two actions that conflict with each other, and
defines when data races take place. There are a number of ways to
induce a happens-before ordering, including:
* Each action in a thread happens-before every subsequent action in that thread.
* An unlock on a monitor happens-before every subsequent lock on that monitor.
* A write to a volatile field happens-before every subsequent read of that volatile.
* A call to start() on a thread happens-before any actions in the started thread.
* All actions in a thread happen-before any other thread successfully returns from a join() on
that thread.
* If an action a happens-before an action b, and b happens before an action c, then a happensbefore c.
For described example we have following guarantees:
- writeLock happens before writeUnLock (they lock the same monitor)
- readLock happens before readUnLock (they lock the same monitor)
- readLock and writeLock are mutually exclusive (they implemented this way)
Execution order then would be writeLock writeUnlock, readLock readUnlock
or readLock readUnlock, writeLock writeUnlock
There is no guarantee when mutateDocument and readDocument happen.
JVM could execute the use case is this way:
Thread 1 Thread 2
mutateDocument readDocument
writeLock
writeUnlock
readLock
readUnlock
The same could happen for two threads mutating the document.
That leads to document model corruption.
(Swing in general does not pay attention to java memory model. The bug
on this will be opened shortly)
2. getting readLock while having writeLock does nothing assuming that
having write lock grants read permission. It might lead to some unexpected problems.
Consider use case:
writeLock
readLock
writeUnlock
doSomething
readUnlock
doSomething will be executed without readLock.
readUnlock will throw StateInvariantError(BAD_LOCK_STATE) becuase
there are no readers registered.
3. readUnlock does not check whether the current thread has acquired readLock.
It might lead to some hard to debug problems.
4. writeUnlock does not check whether the current thread is write lock owner. It
might lead to document model corruptions which is hard to debug.
To address all these issues I suggest to use java.util.concurrent.locks.ReentrantReadWriteLock
ReentrantReadWriteLock was designed exactly for the functionality we are looking for.
Most importantly it addresses the first issue (JMM problem)
From java doc for ReentrantLock
----
A reentrant mutual exclusion Lock with the same basic behavior and
semantics as the implicit monitor lock accessed using synchronized
methods and statements, but with extended capabilities.
----
###@###.### 2004-12-17 01:25:18 GMT