puniverse / quasar

Fibers, Channels and Actors for the JVM
http://docs.paralleluniverse.co/quasar/
Other
4.56k stars 574 forks source link

co.paralleluniverse.strands.concurrent.ReentrantReadWriteLock issue #235

Closed HellScre4m closed 7 years ago

HellScre4m commented 7 years ago

Hi. Thanks for providing such a great tool hope it is going to be integrated to new JDK. Based on docs:

co.paralleluniverse.strands.concurrent.ReentrantReadWriteLock.WriteLock @Suspendable public void lock() Acquires the write lock. Acquires the write lock if neither the read nor write lock are held by another strand and returns immediately, setting the write lock hold count to one. If the current strand already holds the write lock then the hold count is incremented by one and the method returns immediately. If the lock is held by another strand then the current strand becomes disabled for strand scheduling purposes and lies dormant until the write lock has been acquired, at which time the write lock hold count is set to one.

This means if the current Strand already holds read lock, it should be able to acquire write lock. This is a piece of code by me:

System.out.println(requestWaitingLock.getReadHoldCount());
System.out.println(requestWaitingLock.getReadLockCount());
System.out.println(requestWaitingLock.isWriteLocked());
requestWaitingLock.writeLock().lock();
System.out.println("done");

And this is output:

1
1
false

The fiber gets blocked. In ReEnterantReadWriteLock.java line:391 c=65536 and w=0

pron commented 7 years ago

Hi. Your assumption that

This means if the current Strand already holds read lock, it should be able to acquire write lock.

is untrue, although I can see how you can interpret the documentation to mean that. This is called "lock upgrade", which is not supported by any JDK lock (and their fiber-compatible implementations in Quasar) as it guarantees deadlocks. Consider the program that obtains a read lock, does some work, and then upgrades. Two threads running the program are guaranteed to deadlock, no matter which tries to upgrade first, as long as their reads overlap (which is perfectly OK).

You should be able to downgrade a lock by obtaining the write lock, then the read lock, and then releasing the write lock.

HellScre4m commented 7 years ago

Well you are correct. However my fiber is a worker fiber which do maintenance jobs and I'm certain that other fibers don't upgrade lock, they just acquire read or write lock at a time, but according to your description it is reasonable that a re-enterant lock doesn't approve lock upgrading.My bad. Thanks for replying.

pron commented 7 years ago

The general approach is to grab a read lock, test for the condition that would require to upgrade, and if it holds, release the lock, acquire a write lock, test the condition again under the write lock, and if it holds, do the write operation.