On Fri, Sep 7, 2012 at 2:39 PM, Lebling, David (US SSA)
<[email protected]> wrote:
> There is a single service (and JVM) that writes the models (at least in this 
> case), and many that read them. There is a single Store (and hence 
> SDBConnection) for the service.

I'm sorry, I'm not sure I follow.  Let me mirror this back, and please
correct me if I'm wrong.  There is a single JVM running a bunch of
threads.  One of these threads writes, and the rest only read.  Since
it's all within the same JVM (and there's only one store), there's
only one SDBConnection.

> I originally wrote the code so that it used the 
> model.enterCriticalSection/model.leaveCriticalSection methods. This did not 
> seem to prevent other threads from writing the same model inside the critical 
> section.
>
> My belief is that model.begin/model.commit aren't permitted to nest, so it's 
> key to avoid one thread trying to do a transaction when another already is.
>
> So, I tried doing both: model.enterCriticalSection + model.begin, finishing 
> with model.commit + model.leaveCriticalSection. That doesn't seem to do the 
> trick either. I'm still getting "already in transaction," meaning other 
> threads are trying to write the same model and not being blocked by the 
> critical section.
>
> So, is the ModelLock not a thread-safe lock?

I'm not sure what the purpose of the lock would be if it weren't
thread safe;  it's there to permit concurrent access to a model.  The
model generation code

Model model = SDBFactory.connectNamedModel(store, name);

can produce different models on different invocation, and hence the
Locks would apply to different models, but the transaction handler can
be the same for them.  After a coworker ran a quick test, it looks
like the following can happen.

Model m1 = SDBFactory.connectNamedModel(store, name);
Model m2 = SDBFactory.connectNamedModel(store, name);

m1 and m2 are distinct models, so their enter/leaveCriticalSections
aren't going to interfere; you'll be able to enter both critical
sections at once.  However, they're built from the same underlying
Store, and

m1.getTransactionHandler() == m2.getTransactionHandler()

so when you begin() with m1, and subsequently begin() with m2, you're
getting the nesting that you're seeing.  So, you could either:

1) be sure to use the *same* model everywhere so that the
enter/leaveCriticalSections do what you want; or
2) give each writing thread its own Store and connection, and don't
use begin/commit in the reading threads.  You shouldn't need to use
enter/leaveCriticalSection at all in this case. (The writers will be
covered by begin/commit, and the readers don't have to worry about
read locks since nothing will ever be writing to those models (the
only model getting written to is the one that the writer has access
to).)

The first is easier if you'll only be using one JVM, but the second
should scale to multiple JVMs.

//JT
-- 
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/

Reply via email to