[concurrency-interest] Language extensions for java.util.concurrent?

Dawid Kurzyniec dawidk at mathcs.emory.edu
Thu Nov 10 13:37:35 EST 2005


Jeremy Manson wrote:

> Dawid Kurzyniec wrote:
>
>> Now, as the dust has settled and java.util.concurrent is a core 
>> library, I am wondering if the next step should be to propose 
>> language extensions to simplify usage of new tools, particularly 
>> locks and atomics? For instance:
>>
>> class A {
>>  atomic int a;
>>  final Lock lock = new ReentrantLock();
>>  void foo() {
>>    ++a; // -> incrementAndGet()
>>    a ?= 5, 8; // ->compareAndSet(5, 8)
>>    lock.lock() { // ->lock(); try { ... } finally { unlock(); }
>>      // do stuff with the lock held
>>    }
>>  }
>> }
>>
>> Precedence for interface-based syntax support has been set by the 
>> Iterable, and atomic is essentially a stronger incarnation of 
>> volatile. So why not?
>>
>
> Three things:
>
> First, I don't think you would be able to convince the powers that be 
> to introduce new syntax to support an API.  It tends to be something 
> they don't like.  Generally, their feeling seems to be that APIs are 
> the correct way to extend the language.  Which is why we get APIs that 
> require rewrites of the entire system, like RTSJ and Isolates.
>
> Of course, you can argue about the basic correctness of this view.  
> And you can argue about the presence of autoboxing and foreach loops.
>
Sure, they are, and they ought to be, very conservative about the 
language. But nonwithstanding, we see the language evolving, with 
changes nearly every major release. Inner classes, anonymous array 
expressions, class literals, blank finals, final parameters in 1.1, 
strictfp in 1.2, assert in 1.4, generics, autoboxing, foreach loops, 
varargs, concise array literals in 5.0.

Personally I don't have a problem with using j.u.c. merely as the API, 
but the concurrency is already a part of the language anyway, so I think 
that a bit of syntactic sugar for locks and atomics could decrease the 
dichotomy between intrinsic locks and volatiles on one side and explicit 
locks and atomics on the other. After all, this is a very special API, 
requiring explicit JVM support (atomics and park/unpark), and receiving 
special treatment already (deadlock detection for explicit locks). So, 
if there is any API for which I would welcome language support, it would 
be this one.

> Second, I, personally, would be more inclined to want to see a general 
> purpose atomic block.  Something like this:
>
> class A {
>  int a;
>  final Lock lock = new ReentrantLock();
>  void foo() {
>    atomic {
>      ++a;
>    }
>    atomic {
>      if (a == 5) {
>        a = 8;
>      }
>    }
>  }
> }
>
>
> Compilers could do the appropriate replacement, changing the first 
> block to an increment and the second to something like a CAS.  The 
> syntax could also be used to make multiple statements atomic, rather 
> than being restricted to a single statement.  There is some momentum 
> for such a creature in the academic community.

I am not sure how multiple statements could be make atomic without 
introducing mutual exclusion. But if you go there, the boundary between 
blocking and non-blocking statements becomes blurry... I feel a bit 
uneasy about that.

Also, the syntax for CAS is actually longer in this form than 
a.compareAndSet().

Anyway, I am not saying I have all the answers. I am just curious what 
other people may think in general about introducing language extensions 
like this to support this API.

In particular, if I had lock.lock() { ... } (and lock.tryLock() { ... } 
etc.), I would be more inclined to move away from intrinsic locks 
towards explicit locks.

Perhaps the idea could be generalized to allow general constructs of the 
form foo.bar() { ... }, with before- and after- actions for bar() 
defined by the class via annotations, and inserted by the source 
compiler as needed. This would also in some sense generalize the 
constructor invocation syntax for anonymous inner classes. Such a 
general mechanism could benefit other APIs that rely on before/after 
pattern. For instance, I can imagine a version of doPrivileged like this:

AccessController.doPrivileged(acc) {
   // statements here;
   // can read/write local variables from enclosing block
}

The remaining questions are what to do with a returned value (if the 
method is non-null), and how to handle exceptions. One possible solution:

try {
  Socket s = pool.getSocket() {
    // after-action returns the socket to the pool, but only if there 
was no IOException
  }
}
catch (IOException e) {
  // socket could not be obtained, or broken connection
  // handle...
}

Regards,
Dawid



More information about the Concurrency-interest mailing list