Scott Eade <[EMAIL PROTECTED]> writes:
> Shouldn't the TORQUE_3_0_BRANCH have had a TORQUE_3_0_1
> tag added with the release of 3.0.1?
>
> I guess there is little point if there is not likely to
> be a 3.0.2 (i.e. efforts are now focused on 3.1).
What do people think about putting this to get this deadlock fix into
a 3.0.2? I ask because I have seen it fatal to an entire web
application.
dlr 2003/06/19 17:41:18
Modified: src/java/org/apache/torque/manager AbstractBaseManager.java
MethodResultCache.java
Log:
Corrected deadly multi-CPU thread deadlock problem discovered by Ed
Korthof <[EMAIL PROTECTED]> and John McNally <[EMAIL PROTECTED]>. The
problem was due to emulation of synchronization using an int counter
(to improve performance by avoiding Java "synchronized" keyword).
Post-increment and decrement operators compile to three op codes (with
Sun's JDK 1.3.1 for Linux), unsafe on a multi-CPU box.
* src/java/org/apache/torque/manager/AbstractBaseManager.java
lockCache, inGet, cacheGet(), removeInstanceImpl(),
putInstanceImpl(): Removed use of lockeCache and inGet instance
fields, replaced by consistent use of Java's "synchronized" keyword
(on the current instance, "this").
getMethodResultCache(), addCacheListenerImpl(), createSubsetList(),
readObject(): Added JavaDoc.
* src/java/org/apache/torque/manager/MethodResultCache.java
lockCache, getImpl(), putImpl(), get(): Removed use of lockeCache
instance fields, replaced by consistent use of Java's "synchronized"
keyword (on the current instance, "this").
remove(): Added error messages to several method overloads.
Ed Korthof <[EMAIL PROTECTED]> supplied some test code:
Subject: test code demonstrating the lack of atomicity in increment/decrement
Date: Wed, 18 Jun 2003 19:16:53 -0700
This took a while to fail on a single CPU box ... but it fails pretty
quickly on a multi-cpu box.
thanks --
Ed
--
+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=
| Ed Korthof | [EMAIL PROTECTED] | 650-228-2527 |
+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=+=-=
[2. text/plain; test.java]...
import java.util.HashMap;
public class test
{
int i = 0;
boolean lock = false;
HashMap map = new HashMap();
int testThreads = 2;
public static void main(String argv[]) throws Exception {
new test().runTest();
}
public void runTest() throws Exception {
map.put("test", new Long(System.currentTimeMillis()));
for (int j = 0; j < testThreads; ++j) {
Runnable worker = new Runnable() {
long current = 0;
public void run() {
while(true) {
if (lock) {
synchronized(this) {
Object item = map.get("test");
}
}
else {
i++;
Long item = (Long)map.get("test");
current += item.longValue() +
System.currentTimeMillis();
i--;
}
}
}
};
Thread nextThread = new Thread(worker, "worker " + j);
nextThread.start();
map.put("worker" + j, nextThread);
System.err.println("created worker: " + j + " => " + nextThread);
}
while (true) {
synchronized(this) {
lock = true;
Thread.yield();
while (i > 0) {
System.err.println("i > 0: " + i);
Thread.sleep(100);
}
map.put("test", new Long(System.currentTimeMillis()));
lock = false;
if (i < 0) {
System.err.println("i < 0: " + i);
}
System.err.println("one iteration");
}
Thread.sleep(500);
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]