Especially about synchronization, when I thought I knew the subject pretty well.
I have to go and read over my old code to see wether I made some of the mistakes talked about in
those articles... although I doubt it because when it comes to threading I tend to be on the safe side
and not do smart optimizations. My telephony applications have hundreds of threads but each one is
blocked a lot of the time so I dont worry much about synchronization overhead.
Following, I propose a DCL method which *I know* is formally incorrect but if tuned rightly will
give an almost optimal solution. Yes, it's a stupid, unelegant method but will allow us to move on
to other subjects!!
<pre>
public class Resource
{ private static final long SAFE_TIME= 98765432; // safe lapse of time, in ms, for the complete creation of one Resource
private long whenCreated= Long.MAX_VALUE; // almost 3 million centuries from now!
private static Resource r= null;
public static Resource getResource()
{ if ( (System.currentTimeMillis() - whenCreated) < SAFE_TIME ) // we're not safe yet!
{ synchronized (Resource.class)
{ if (r == null)
{ r= new Resource();
whenCreated= System.currentTimeMillis();
}
}
}
return r; }
//----- Rest of Resource class here }
</pre>
Explanation:
The *whole point* of DCL was not having to enter a synchronized block *every time* during the life of the program (which could be running for days or months).
The original smart ways to do it was to check wether the "r" variable had already been assigned because the naive thinking (me, up to a few days ago) took us
to believe thay by then the Resource constructor was finished. We saw that because of compiler optimization, JIT optimization, CPU's optimization, and cache/memory unit
optimization, we could never be sure of the order in which things were executed and memory read/writes were performed. We are only sure of that on a per-thread basis
and when it comes to "outside" threads we can be sure that the whole synchronized block looks like an atomic operation, provided the "outside" thread although synchronizes
on the same object.
Now, if we have a safe estimate of how long would it take to perform the creation of a new Resource, ever, the longest, under the worst circumstances...
we can have a SAFE_TIME in milliseconds.
Let's say that under the worst assumptions, the syncrhonized block will never take more than 2 minutes to execute completely. Then we can set the constant
SAFE_TIME= 120000; // 2 minutes, in milliseconds
Yes, this may make a thread enter the synchronized block unnecessarily if another thread already entered less than 2 minutes ago. The Resource has already been created
and the check for null will be false... Aw gee... we wasted time entering the synch!!
Worry not! After 2 minutes, and for the remaining running life of your program the first "if" will take care of it!!!
We get 99.99% the efficiency of a DCL... if worked, that is!!!
But, as long as I can tell, this method works... provided you choose SAFE_TIME correctly and... er... safely...
Ah! And don�t worry to document your code!!! SAFE_TIME is a bold assumption that may change over time, or when another programmer has to modify your code.
Or Long.MAX_VALUE milliseconds from now.... don't forget Y2K :-)
Some may say it's stupid and you shouldn't have wasted your time reading this post.
All constructive comments will be accepted, all flames will be redirected to /dev/null
BarZ
--- You are currently subscribed to jdjlist as: [EMAIL PROTECTED] To unsubscribe send a blank email to [EMAIL PROTECTED] http://www.sys-con.com/fusetalk
