Hi,
Under the new JMM, one view of the purpose of synchronization is to allow
the programmer to introduce an explicit happens-before relationship between
actions that occur in different threads.
However, it is quite heavyweight. It introduces that relationship for a
vast array of actions for which it was never required. In practical terms,
it can result in the flushing of memory caches, at considerable execution cost.
My interest in this comes from my current need to implement a system
configuration cache that is frequently accessed, but rarely modified. At
the moment, I have two approaches: synchronize every access, or use a
thread-local subcache. Neither of these is particularly attractive.
What I'm looking for is a mechanism that introduces a happens-before
relationship between some defined action in a thread, and some other
defined action that will occur at a more-or-less arbitrary future time, and
in a different thread.
In thread t1, let there be an action a1, which causes action a2 to occur at
some future time in some undetermined thread (call it t2). Action a1
happens before action a2.
For every thread t' let there be some action x' such that we can divide the
actions of thread t' into two groups, those that happen before x', and
those that happen after x'.
Action a1 happens before every x'. Action a2 happens after every x'.
The point of this is that actions caused by a2 in all threads must
necessarily happen after a1 (even if they manage to happen before a2).
As an example, prior to a1, t1 could construct an unsynchronized cache, and
a synchronized proxy for it. The reference to the proxy would be published,
and then a1 would occur. Action a2 would consist of replacing the reference
to the synchronized proxy by the reference to the unsynchronized cache.
Thus the synchronization cost of accessing the cache would only be born for
a short period after the cache is changed.
Lest people be concerned by the potential complexity of what I ask, I'd
mention that it seems to me that garbage collection already introduces the
points x' (all at the same time, in fact, which I don't require), and that
one implementation of the mechanism would be a class of the form:
public abstract class Barrier
{
protected abstract doActionA2();
protected void finalize()
throws Throwable
{
doActionA2();
}
}
The action a1 would consist of constructing an instance of Barrier,
overriding doActionA2().
This is not to say that the class as I've described it fits the bill. An
aggressive optimiser might conceivably surmise that the object becomes
unreachable immediately, and call the finalize method (in a separate
thread) without further ado.
Comments?
Sylvia.
-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:52 EDT