RE: JavaMemoryModel: init methods

From: Doug Lea (dl@cs.oswego.edu)
Date: Tue Oct 03 2000 - 07:53:06 EDT


> There are too
> many ways to cheat and get better performance. And some of the more
> interesting cheats are even correct, e.g. updating a cache with an atomic
> pointer assignment and not locking on lookup, or "or"ing boolean results by
> initializing a global to "false" and then asynchronously writing "true" into
> it, potentially from multiple threads. Even if the program in question
> doesn't care enough about performance to do this, one if the library writers
> will have.

However, any such trick used by library writers should work regardless
of how badly application code writers mis-synchronize their code. The
notion of "work" gets fuzzy here, but as always in Java (unlike most
languages), even bad code cannot violate minimal safety guarantees.
Note that it can be challenging to say what the term "NOT THREAD-SAFE"
applied to a method or class means in Java. Generally, it means that
only a subset of postconditions/invariants/effects hold in the absence
of holding certain locks at certain times, but this subset is normally
larger in Java than it is in C.

In any case, it would be a good idea, that I'll probably undertake, to
enumerate known legal and illegal tricks along these lines under
revised JMM. In fact, I still have several unreleased classes for my
util.concurrent that use some of these that I will only be able to
include when JMM is revised to clarify that they are legal. (For
example, the ConcurrentReaderHashMap class I once posted that you can
find in the mail archives for this list.)

> this is almost exactly what you
> need to do to remove the synchronization in the beans example? You need to
> recognize that field values are constant once the object becomes public, and
> then remove the synchronization on the bean from field accesses, eventhough
> the bean is accessible from multiple threads?
>

Continuing a previous digression: An unfortunate aspect of proposed
revised JMM is that such manipulations cannot be expressed by code
authors or by source-to-source analytic tools. We only support one
way to get "synchronize once" semantics: use final fields in
constructors. In contrast, Posix contains a "pthread_once" construct
(although it is also not very general). But there doesn't seem to be
any place to hang such semantics in Java outside of the narrow rules
surrounding finals in constructors. The only proposed extension for
dealing with this that I know of is David Holmes suggestion of
allowing "volatile" and "final" to be clause modifiers, as in:

class C {
  void f() {
    final { init_code(); }
  }

  void g() {
    volatile { code_needing_barrier(); }
  }
}

But beyond the fact that these entail syntax changes (which we want to
avoid for purposes of revising memory model), they complicate language
semantics. For example, how can you verify that no field written in a
"final" clause is ever written again? And how can you tell exactly
which fields need barriers on reads (on platforms requiring this)?
The current rules restricting writes to finals be in constructors make
these issues tractable, but they don't extend in any way I can see to
these more general constructions.

Can anyone think of alternatives? It would be nice to specify
mechanisms that, even if never used by application writers, would make
it possible for library writers and analytic tools to say what they
mean. The again, lots of things would be nice to have, but aren't
worth changing the language for. This might be one of them.

-- 
Doug Lea, Computer Science Department, SUNY Oswego, Oswego, NY 13126 USA
dl@cs.oswego.edu 315-341-2688 FAX:315-341-5424 http://gee.cs.oswego.edu/  
-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel



This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:28 EDT