Re: concurrency and starting a synchronized block
I spent a whole bunch of time looking into how various caches/collections handled this issue when I was designing Whirlycache [1] and the cleanest solution that is available today, as others have pointed out, is Doug Lea's util.concurrent package. The high-level explanation of how Doug Lea's ConcurrentHashMap works is that it has 32 internal buckets and a fast hashing algorithm. It only synchronizes internally on the bucket that is being modified, thereby leaving the other n buckets free to do whatever they need. So you can conceivably have 32 concurrent threads reading and/or writing depending on how the hashing algorithm causes the buckets to be synchronized. It's a lot faster than a java.util.HashMap when you have many threads reading and writing. I think the 32 fixed bucket size limit was removed when these classes were ported to JDK 1.5. Depending on what you are doing, you basically have 3 choices when you're dealing with multithreaded access/modification to a collection: 1) don't synchronize and watch failures happen 2) synchronize on the containing object's monitor: ... public synchronized whatever(Object arg1) {...} public synchronized something() {...} ... 3) use more granular synch locks, if possible: ... private Object whatever = new Object(); private Object something = new Object(); public whatever(Object arg1) { synchronized (whatever) { ... } } public something(Object arg1) { synchronized (something) { ... } } Making the locks more granular can make a huge difference, but it's only possible if your particular case will allow for it. But it's definitely worth investigating rather than blindly using 'synchronized' in method signatures... which turns out to be not-that-slow anyway. YMMV. phil. [1] http://whirlycache.dev.java.net/ Torsten Curdt wrote: Guys, forgive me if this too off topic... ...but I thought it is somehow related to collections that's why I am bringing it up here anyway. I bet someone of you will know Consider this code... Object o = map.get(key); if (o == null) { synchronized(map) { map.put(key,new Object()); } } 99% of the time the gets on the map are going to return an object. That's why I would like to avoid synchronizing the get access. Now since a put might corrupt the data it has to be synchronized. Since the get, the comparison and the put are not in a synchronized block I might loose objects ...but for this particular usecase that's ok. Now what really got me thinking is the concurrent sychronized and non-synchronized access. What happens when Thread A is in doing a get while Thread B is entering the sychronized block for the put? I assume that since the map object is not locked it will go straight into the put and bang ...right? Somehow this looks like the optimal usecase for the FastHashMap from collections ...but since this code needs to be very portable this might be a problem because of the double-checked locking idiom. Another option would be using the StaticBucketMap. What do you guys think? If you consider this too OT please reply off list. cheers -- Torsten -- Whirlycott Philip Jacob [EMAIL PROTECTED] http://www.whirlycott.com/phil/ - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: concurrency and starting a synchronized block
Exactly - most books and documentation about resource exclusion about this make it abundantly clear that synchronized methods shouldn't call each other for this very reason. Thanks for adding that point. phil. Oliver Zeigermann wrote: On Thu, 10 Feb 2005 13:09:14 -0500, WHIRLYCOTT [EMAIL PROTECTED] wrote: 2) synchronize on the containing object's monitor: ... public synchronized whatever(Object arg1) {...} public synchronized something() {...} ... Blindly doing this can easily lead to deadlocks. Consider thread #1 in method whatever accesses another synchronized object and needs to wait for thread #2 to release the lock on it. Now thread #2 tries to access method something and - of course - needs to wait for thread #1 to release the lock on that first objec. Now both threads mutually wait for each other and you have a deadlock. Oliver - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] -- Whirlycott Philip Jacob [EMAIL PROTECTED] http://www.whirlycott.com/phil/ - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: concurrency and starting a synchronized block
I guess this thread should end soon, but while we're still having some fun ... ;) ConcurrentHashMap can do concurrent put() operations and concurrent get() operations... and that's the tricky part. I just love all that stuff that Doug Lea has done. For those who haven't looked at util.concurrent, I recommend it. Sounds like others do as well. phil. Kevin A. Burton wrote: Torsten Curdt wrote: Guys, forgive me if this too off topic... ...but I thought it is somehow related to collections that's why I am bringing it up here anyway. I bet someone of you will know Ignore what everyone else says on this list topic. ha. Use a ReentrantReadWriteLock from JDK 1.5. There's a backport to JDK 1.4 out on the net. Google for backport concurrent oswego or something Then you can do a lock.readLock().lock() on our gets and then do a writeLock on your puts. the writeLock will backup the readlock but if you only have readlocks they can all happen at once. Normally though its not too big a deal since gets() on a hashtable are O(1) Kevin -- Whirlycott Philip Jacob [EMAIL PROTECTED] http://www.whirlycott.com/phil/ - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: concurrency and starting a synchronized block
There's also the original version here: http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html What does the backport offer that the original util.concurrent lib doesn't offer? phil. Kevin A. Burton wrote: WHIRLYCOTT wrote: I guess this thread should end soon, but while we're still having some fun ... ;) ConcurrentHashMap can do concurrent put() operations and concurrent get() operations... and that's the tricky part. I just love all that stuff that Doug Lea has done. For those who haven't looked at util.concurrent, I recommend it. Sounds like others do as well. I know... its good stuff. I blogged about it: http://www.peerfear.org/rss/permalink/2004/12/19/TheJavaUtilConcurrentPackageAndThreadConcurrency/ All the fun toys that are available ;) Kevin -- Whirlycott Philip Jacob [EMAIL PROTECTED] http://www.whirlycott.com/phil/ - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: svn commit: r149313 - in jakarta/commons/sandbox/javaflow/trunk/src: java/org/apache/commons/javaflow/ java/org/apache/commons/javaflow/bytecode/bcel/ test/org/apache/commons/javaflow/ test/org/apache/commons/javaflow/testcode/
Torsten Curdt wrote: Well, the point is that the file writing code is temporary anyway. I should go away in the near future. That's why fixing it is not that important. Yes, I was going to ask about that one... can you let me in on your plans for this? I agree that it should go away, but I haven't spent any time rethinking this. Btw: for some reason I've some problem applying your patches with eclipse :-/ ...most of the hunks are not being found. How goofy. The subclipse client isn't as painfree as the cvs one from what I can tell. The team synchronizing perspective occasionally indicates to me that there differences between local and remote when there are none. I'm not sure what could cause this... will investigate. phil. - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: [javaflow] test cases in junit?
Torsten Curdt wrote: * I added a ContinuationException class that can be thrown to clients using this code instead of stuff like java.lang.reflect.InvocationTargetException that is dependent on the underlying bytecode toolkit. That class was missing in your patch. Besides I am wondering what you mean by dependand on the bytecode toolkit?! There was a note in TODO about investigating using ASM instead of BCEL. Without even looking in detail at ASM, my guess is that it will throw different exceptions than BCEL when manipulating the bytecode, etc. My idea was that we could throw a ContinuationException instead of the underlying FooException that either BCEL or ASM uses to insulate any calling classes from having to change in the event of a switch from BCEL to ASM. Please have a look into the one I've committed. Continueing from the very same continuation is totally ok! Keep the tree of continuations in mind! Ok, thanks for correcting me. * In the TODO file, you mention something about removing the Continuable and ContinuationCapable marker interfaces. Can you please elaborate on the reasons behind that? The Continuable marks classes that should be rewritten. The ContinuationCapable mark classes that have been rewritten. IMO this can all go away. We could define that on a package scope. E.g. via regexp. Going for a decend callflow analyses would even figure out the needed rewrites by itself. Might be some work though... I think I understand the reason why both of these interfaces exist. However, if the intent is to be able to use Continuation.suspend() within any class without having to implement Continuable on that class, then maybe just do away with Continuable and keep ContinuationCapable as the marker for that class after it has been rewritten. What benefit does the regex approach provide? Callflow analyses seems like it could be messy. And I think just tagging the rewritten class with this interface is pretty transparent, no? phil. -- Whirlycott Philip Jacob [EMAIL PROTECTED] http://www.whirlycott.com/phil/ - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: svn commit: r149313 - in jakarta/commons/sandbox/javaflow/trunk/src: java/org/apache/commons/javaflow/ java/org/apache/commons/javaflow/bytecode/bcel/ test/org/apache/commons/javaflow/ test/org/apache/commons/javaflow/testcode/
thrown when a continuable class + * is used incorrectly (i.e. without the ContinuationClassLoader). + * @throws Exception + */ +public void testIncorrectUsageWithNormalClassLoader() throws Exception { +log.debug(Testing incorrect use of continuation...); +boolean exceptionThrown = false; +try { +final Calculator c = new Calculator(); +c.main(); +} catch (final Exception e) { +log.debug(Catching a + e); +assertTrue(e instanceof IllegalStateException); +exceptionThrown = true; +} +assertTrue(exceptionThrown); +} + + +/** * The junit tests are preferred over running this main() method. * @param args * @throws Exception @@ -89,5 +111,6 @@ public static void main(final String[] args) throws Exception { final ContinuationClassLoaderTestCase t = new ContinuationClassLoaderTestCase(); t.testCalculator(); +t.testIncorrectUsageWithNormalClassLoader(); } } Modified: jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/ContinuationCompilingClassLoaderTestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/ContinuationCompilingClassLoaderTestCase.java?view=diffr1=149312r2=149313 == --- jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/ContinuationCompilingClassLoaderTestCase.java (original) +++ jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/ContinuationCompilingClassLoaderTestCase.java Mon Jan 31 14:53:31 2005 @@ -22,15 +22,19 @@ import org.apache.commons.logging.LogFactory; import org.apache.jci.CompilingClassLoader; +import junit.framework.TestCase; + /** * @author tcurdt * */ -public final class ContinuationCompilingClassLoaderTestCase { +public final class ContinuationCompilingClassLoaderTestCase extends TestCase { + private final static Log log = LogFactory.getLog(ContinuationCompilingClassLoaderTestCase.class); -private void testReloading() throws Exception { +public void testReloading() throws Exception { +/* final CompilingClassLoader cl = new ContinuationCompilingClassLoader( this.getClass().getClassLoader(), new File(/home/tcurdt/dev/jci/classes) @@ -50,7 +54,7 @@ Thread.sleep(2000); } - + */ } public static void main(String[] args) throws Exception { Modified: jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/testcode/Calculator.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/testcode/Calculator.java?view=diffr1=149312r2=149313 == --- jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/testcode/Calculator.java (original) +++ jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/testcode/Calculator.java Mon Jan 31 14:53:31 2005 @@ -28,18 +28,33 @@ */ public final class Calculator implements Continuable, Serializable { -/** - * Logger. - */ private static final Log log = LogFactory.getLog(Calculator.class); + +private int global = 0; +private int local = 0; public void main() { -log.debug(Calculator1); +int l = 0; + +log.debug(Start of Calculator: g= + global + l= + local); + +global++; +local = ++l; -Continuation.suspend(); +log.debug(Calculator Step 1: g= + global + l= + local); -log.debug(Calculator2); +Continuation.suspend(); +log.debug(Calculator Step 2: g= + global + l= + local); + +global++; +local = ++l; + +log.debug(End of Calculator: g= + global + l= + local); +} + +public String toString() { +return + global + . + local; } } - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] -- Whirlycott Philip Jacob [EMAIL PROTECTED] http://www.whirlycott.com/phil/ - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: [javaflow] test cases in junit?
Ok, here's a start, anyway. Some notes: * The simplelog setup wasn't working at all for me for anything less than info, so I added log4j into the project.xml. Works fine now. Not sure if you were having a similar problem? junit is also added to project.xml. * There are some references to /home/tcurdt in .classpath. I didn't touch them. Does this even belong in svn? * I added a ContinuationException class that can be thrown to clients using this code instead of stuff like java.lang.reflect.InvocationTargetException that is dependent on the underlying bytecode toolkit. * Added some serialVersionUID fields to Serializable classes. * The test case causes an exception to be thrown and tests for it, so be aware of that when you see the stacktrace in the output. * In the TODO file, you mention something about removing the Continuable and ContinuationCapable marker interfaces. Can you please elaborate on the reasons behind that? Just starting off small for now - more soon. phil. Torsten Curdt wrote: Any objections to receiving test cases using junit? Phil, of course not! :) ...actually it was my plan using junit for that. cheers -- Torsten - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] -- Whirlycott Philip Jacob [EMAIL PROTECTED] http://www.whirlycott.com/phil/ Index: C:/Documents and Settings/pjacob/My Documents/workspace/javaflow/.classpath === --- C:/Documents and Settings/pjacob/My Documents/workspace/javaflow/.classpath (revision 149125) +++ C:/Documents and Settings/pjacob/My Documents/workspace/javaflow/.classpath (working copy) @@ -8,5 +8,7 @@ classpathentry kind=var path=MAVEN_REPO/commons-logging/jars/commons-logging-api-1.0.4.jar/ classpathentry kind=var path=MAVEN_REPO/commons-logging/jars/commons-logging-1.0.4.jar/ classpathentry kind=var path=MAVEN_REPO/ant/jars/ant-1.5.3-1.jar/ + classpathentry kind=var path=MAVEN_REPO/junit/jars/junit-3.8.1.jar/ + classpathentry kind=var path=MAVEN_REPO/log4j/jars/log4j-1.2.8.jar/ classpathentry kind=output path=bin/ /classpath Index: C:/Documents and Settings/pjacob/My Documents/workspace/javaflow/project.xml === --- C:/Documents and Settings/pjacob/My Documents/workspace/javaflow/project.xml(revision 149125) +++ C:/Documents and Settings/pjacob/My Documents/workspace/javaflow/project.xml(working copy) @@ -68,6 +68,18 @@ artifactIdant/artifactId version1.5.3-1/version /dependency + + dependency + groupIdjunit/groupId + artifactIdjunit/artifactId + version3.8.1/version + /dependency + + dependency + groupIdlog4j/groupId + artifactIdlog4j/artifactId + version1.2.8/version + /dependency /dependencies /project Index: C:/Documents and Settings/pjacob/My Documents/workspace/javaflow/src/test/org/apache/commons/javaflow/ContinuationClassLoaderTestCase.java === --- C:/Documents and Settings/pjacob/My Documents/workspace/javaflow/src/test/org/apache/commons/javaflow/ContinuationClassLoaderTestCase.java (revision 149125) +++ C:/Documents and Settings/pjacob/My Documents/workspace/javaflow/src/test/org/apache/commons/javaflow/ContinuationClassLoaderTestCase.java (working copy) @@ -18,6 +18,8 @@ import java.lang.reflect.Method; import java.util.Map; +import junit.framework.TestCase; + import org.apache.commons.javaflow.utils.ReflectionUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -27,40 +29,70 @@ * @author tcurdt * */ -public final class ContinuationClassLoaderTestCase { +public final class ContinuationClassLoaderTestCase extends TestCase { +/** + * Logger. + */ private final static Log log = LogFactory.getLog(ContinuationClassLoaderTestCase.class); -private void testCalculator() throws Exception { +public void testCalculator() throws Exception { +log.debug(Doing testCalculator()); + +final String calculatorTestClass = org.apache.commons.javaflow.testcode.Calculator; + final ClassLoader cl = new ContinuationClassLoader(getClass().getClassLoader()); -final Class clazz = cl.loadClass(org.apache.commons.javaflow.testcode.Calculator); +final Class clazz = cl.loadClass(calculatorTestClass); +assertNotNull(clazz); -final Map m = ReflectionUtils.discoverMethods(clazz); +//This map contains methods indexed by their names (Strings). +final Map methods = ReflectionUtils.discoverMethods(clazz
[javaflow] test cases in junit?
Torsten - Any objections to receiving test cases using junit? phil. -- Whirlycott Philip Jacob [EMAIL PROTECTED] http://www.whirlycott.com/phil/ - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]