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/
