[
https://issues.apache.org/jira/browse/JENA-522?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13748578#comment-13748578
]
Andy Seaborne commented on JENA-522:
------------------------------------
I agree there is some some of problem but I think it's something different.
The check DatasetGraphWithLock.checkActive() is wrong. It's not thread
sensitive.
An example: it prints and pauses, then prints again. I see partial overlaps
as would be expected by multiple threads in the read region but not all threads
print anything. They have died at {{dsg.begin}}. If you comment out in
DatasetGraphWithLock as below ...
{noformat}
@Override
protected void checkActive()
{
// if ( ! isInTransaction() )
// throw new JenaLockException("Not in a locked region") ;
}
@Override
protected void checkNotActive()
{
// if ( isInTransaction() )
// throw new JenaLockException("Currently in a locked region") ;
}
{noformat}
... then I get the expected overlaps fro the code below.
{{isInTransaction}} is being set wrongly - it needs to be a thread local (like
it is in DatasetGraphTransaction)
{noformat}
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool() ;
final DatasetGraphWithLock dsg = new
DatasetGraphWithLock(DatasetGraphFactory.createMem());
Callable<Boolean> callable = new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
int x = counter.incrementAndGet() ;
// Get a read lock
try { dsg.begin(ReadWrite.READ); }
catch (RuntimeException ex) {
System.err.println("Exception in .begin ("+x+")") ;
ex.printStackTrace(System.err) ;
return false ;
}
// Hold the lock for a short time
try {
System.err.println("Task "+x+" start") ;
Thread.sleep(500);
System.err.println("Task "+x+" finish") ;
} catch (InterruptedException e) {
System.err.println("InterruptedException") ;
e.printStackTrace(System.err);
}
exitCounter.incrementAndGet() ;
try { dsg.commit(); }
catch (RuntimeException ex) {
System.err.println("Exception in .commit ("+x+")") ;
ex.printStackTrace(System.err) ;
return false ;
}
return true;
}
};
int N = 10 ;
for (int i = 0; i < N; i++) {
executor.submit(callable) ;
}
for ( ;; ) {
if ( exitCounter.intValue() != N )
Lib.sleep(500);
}
}
{noformat}
> DatasetGraphWithLock claims to support multiple readers but appears not to
> --------------------------------------------------------------------------
>
> Key: JENA-522
> URL: https://issues.apache.org/jira/browse/JENA-522
> Project: Apache Jena
> Issue Type: Bug
> Components: ARQ
> Affects Versions: Jena 2.10.2
> Reporter: Rob Vesse
> Labels: concurrency, lock, multi-threading
>
> This bug originates out of a StackOverflow question pertaining to jena-text
> http://stackoverflow.com/q/18385738/107591
> However upon investigation the culprit appears to be
> {{DatasetGraphWithLock}}, reproducing my analysis from my SO answer here:
> {quote}
> The issue is that the dataset with inference implicitly uses ARQ's standard
> in-memory Dataset implementation and this does not support transactions.
> However text datasets which correspond to {{DatasetGraphText}} internally
> (and in your stack trace) requires the wrapped dataset to support
> transactions and where they do not wraps them with {{DatasetGraphWithLock}}.
> It is this that appears to be encountering the problem with the lock, the
> documentation states that this should support multiple readers but having
> followed the logic of the code I'm not sure that it actually allows this.
> {quote}
> I put together the following test case which illustrates the issue:
> {noformat}
> @Test
> public synchronized void dsg_with_lock_concurrency_02() throws
> InterruptedException, ExecutionException, TimeoutException {
> ExecutorService executor = Executors.newCachedThreadPool();
> try {
> final DatasetGraphWithLock dsg = new
> DatasetGraphWithLock(DatasetGraphFactory.createMem());
> Callable<Boolean> callable = new Callable<Boolean>() {
> @Override
> public Boolean call() throws Exception {
> // Get a read lock
> dsg.begin(ReadWrite.READ);
> // Hold the lock for a short time
> try {
> Thread.sleep(500);
> } catch (InterruptedException e) {
> // Ignore error
> }
> // Release the lock
> dsg.commit();
> return true;
> }
> };
> // Run the callable a bunch of times
> List<Future<Boolean>> futures = new ArrayList<Future<Boolean>>();
> for (int i = 0; i < 100; i++) {
> futures.add(executor.submit(callable));
> }
> // Check all the futures come back OK
> for (Future<Boolean> f : futures) {
> Assert.assertTrue(f.get(3, TimeUnit.SECONDS));
> }
> } finally {
> executor.shutdownNow();
> }
> }
> {noformat}
> So the problem appears to be that DatasetGraphWithLock claims multi-reader
> support but in reality does not allow this.
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira