[
http://jira.jboss.com/jira/browse/JBAS-5564?page=comments#action_12414826 ]
Adrian Brock commented on JBAS-5564:
------------------------------------
The code looks correct to me.
Let me take it apart... :-)
if (
// If some thread is already invoking on the instance
lockHolder != null)
if (
// And it's not our thread
lockHolder != curThread && (
// There's no transaction so there can be no transactional lock
miTx == null ||
// Or it's some other thread in the same transaction
miTx.equals(holdingTx)))
Then we check for deadlocks and wait...
Your suggestion would only occur if the BeanLock has failed.
i.e. some other thread is invoking on the same shared instance in a different transaction
That should not be possible with a shared cache and a proper lock doing its processing
before this code even runs.
The re-entrance processing is not intended to handle the real (transactional) lock, its
main
purpose is to handle concurrent/recursive invocations outside a transaction or in the
(technically against spec)
two threads with the same transaction.
So my conclusion is that at least one of the following is true:
1) This statement is incorrect:
"I use an own implementation of a BeanLock, which is so far correct an not an issue
in this ticket"
2) You didn't read the FAQ referenced from JBAS-4177
http://wiki.jboss.org/wiki/ChangingTheLockingPolicy
i.e. your custom bean lock is not appropriate for a shared instance cache
3) You have some other issue such as the entity bean's primary key class not
implementing
equals/hashCode() correctly so the cache is handing out the wrong instances
If you want help with your BeanLock use the forums not a bug report.
Probable logical problem in NonReentrantLock
--------------------------------------------
Key: JBAS-5564
URL:
http://jira.jboss.com/jira/browse/JBAS-5564
Project: JBoss Application Server
Issue Type: Bug
Security Level: Public(Everyone can see)
Components: MicroContainer bus, EJB2
Affects Versions: JBossAS-5.0.0.Beta4, JBossAS-5.0.0.Beta3, JBossAS-4.2.2.GA
Environment: None, source code analysis
Reporter: Domagoj Cosic
Assigned To: Alexey Loubyansky
Introduction: My direct problem is distantly related to JBAS-4177. The difference is, I
use an own implementation of a BeanLock, which is so far correct an not an issue in this
ticket, nor is the my original problem that the NonReentrantLock causes. However, my
original problem led me to NonReentrantLock and I analyzed its source code in some depth.
I have a suspicion that there is a serious bug in it.
The problem I want to point at is in the line 143:
Up to the trunk revision there stands:
if(lockHolder != curThread && (miTx == null || miTx.equals(holdingTx)))
There is some contradiction to the description:
"It will throw a ReentranceException if the same thread tries to acquire twice
or the same transaction tries to acquire twice"
For a non re-entrant bean it means, in pseudo code:
if (sameThread or sameTransaction) {
throw new ReentrantException();
} else {
waitForOtherThreadOrTransaction;
on timeout return false;
return true;
}
This description does not apply to an re-entrant bean, but for re-entrant bean it
basically means (in pseudo code):
if (sameThread or sameTransaction) {
return true;
} else {
waitForOtherThreadOrTransaction;
on timeout return false;
return true;
}
I backtracked the code to the previous change, which was revision 16662 dated 27.08.2003
There it stands:
if (lockHolder == Thread.currentThread()) throw new ReentranceException();
if (miTx != null && miTx.equals(holdingTx)) throw new
ReentranceException();
Although this code was for the non re-eantrant case, for the re-entrant case the code
should return true for those cases, where ReentrantException was thrown.
Let us transform this code step by step:
Step 1:
if (lockHolder == Thread.currentThread()) return true;
if (miTx != null && miTx.equals(holdingTx)) return true;
Step 2:
if (lockHolder == Thread.currentThread() || miTx != null &&
miTx.equals(holdingTx)) {
return true;
} else {
wait;
return true;
}
Step 3 (negating):
if (lockHolder != Thread.currentThread() && (miTx == null ||
!miTx.equals(holdingTx))) {
wait;
return true;
} else {
return true;
}
You see the difference? Current code lacks "!" before miTx.equals(holdingTx).
It seems wrong to me and it causes a problem for me, so it would be nice if someone else
takes a look at this.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira