-
Notifications
You must be signed in to change notification settings - Fork 93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Problem with DefaultDataSetLock #366
Comments
@dedeibel thanks for reporting. I'll have a look at it. What makes it more complex, is that this lock is write-reentrant and multiple read reentrant as well, which the other locks do not support. But the issue of the AtomicInteger not being strictly synchronised to the StampedLock could be a (potential) issue. Need more time to investigate this. |
Some preliminary observations:
N.B. AtomicInteger is intrinsically volatile but is IMO not the culprit.
Tried this before and again now but this does not seem to solve the issue. I think your proposal to guard the pessimistic What remains to be checked is:
As mentioned before the non-trivial nature is the re-entrability for write (albeit always the same thread) and multiple reader (in different theads). We all wished several times before that there would be a default JDK implementation for that. But even StampedLock (N.B. not reentrable by itself) -- as you also noted before -- isn't that much used around the web. Again, @dedeibel thanks for reporting and the consise unit-test. This helped a lot to reproduce and isolate that problem. 👍 |
* added DataSetLockStressTest original unit-test idea courtesy Benjamin Peters (@dedeibel) * fixes DataSetLock readLock race issue #366 * modified read-lock and re-introduced atomic guards N.B. only the first reader acquires a lock, subsequent readers increase atomic counter, and only the last remaining reader unlocks. detects race-condition on initial lock and final unlock
Hi,
my application experienced a dead lock that seems to be related to
DefaultDataSetLock
. I can see the following exception shortly before the lock-up. It was not accepting any more incoming data for the dataset after that:I noticed that the writing threads were blocked.
DefaultDataSetLock
uses aStampedLock
internally, the API says that it does "not unlock" the read lock in case of a stamp validation failure (above exception).I created a minimal example test to verify if my problem is reproducible. And it was using a "simple" test case that stressed the data set with multiple writers and readers.
Please see:
5c7d8f6#diff-26f7ddc574723fa7614e1a15765109cd1d4842ec1eab439bf72235eb9f860d63
(https://github.com/GSI-CS-CO/chart-fx/compare/demo-data-set-lock-stress-test)
Execution time can be from around a few seconds to a couple of minutes. If it does not fail, adjust the thread count or just repeat the execution until it does.
The exception confuses me a bit though. I can understand why the stamp validation would fail on an optimistic read but this is not applicable here,
readLock
causes a pessimistic read. Maybe there is a problem regarding thelastReadStamp
handling inDefaultDataSetLock
since it is only guarded by the thread count atomic var but is not synchronized or even volatile.My idea: Shortly after a an unlocking thread changed
readerCount
to zero the next reader could callDefaultDataSetLock
's read lock method and cause thelastReadStamp
to change. The thread that was trying to unlock theStampedLock
before might now use the value returned by the new reader thread.A hint into that direction could be that I could not observe the problem yet with only one reader thread and the error chance increased with the number of reader threads.
I created a
DefaultDataSetLockSynced
to validate my guess and I did not see any failures with this version. However I am not suggesting this version as it is surely driving the use ofStampedLock
into an absurd place. MaybeDefaultDataSetLock
should be changed in a way that thestamp
is only used as a local var (in case of the methods with lambda parameters) or thestamp
is returned to the caller in order to simplify the code and go to a similar interface likeStampedLock
.But I am not completely sure about the
StampedLock
semantics here – it confuses my why a stamp is used at all in the API in case ofreadLock
? UnlessStampedLock
is always a bit optimistic and makes no guarantees (I could not find a note about that in the docs though). In this case we would have to retry reads every time. But I can find no example source on the web that does that when usingreadLock
only when usingtryOptimisticRead
. So I am not suggesting that either.The text was updated successfully, but these errors were encountered: