[concurrency-interest] Immutable object conundrums

Peter Veentjer alarmnummer at gmail.com
Tue Jun 30 09:58:51 EDT 2009


On Tue, Jun 30, 2009 at 3:24 PM, Ashley Williams<ashpublic at mac.com> wrote:
> Sorry I wasn't clear on this one, yes it was a bad example.
>
> In your example I think you are talking about making use of the
> happens-before rule
> knowledge i.e. program-order, volatility and transitivity? This is what I
> was suggesting
> except replacing volatile with atomic.
>
> What I wanted to imply was that if we had some sort of api (better than my
> suggestion)
> to the memory model then we wouldn't need to declare state as final.
> Actually I'm not
> advocating that there should be such an API, I'm just using the argument to
> suggest
> that sometimes use of the final modifier has got nothing to do with
> immutability.

True. But that is why I'm trying to explain as well. In principle you
don't need final fields if you use a volatile write/read, unlock/lock
to transfer an object from one thread to another.

A practical example:

If you use a producer/consumer that communicates through a
blockingqueue, you can use ordinary pojo's as items (without any
volatile, final, atomic etc) because the blockingqueue ensures that
there is a happens before relation between the put of the item and the
take. So your POJO's can be arbitrary complex/deep.

So if you hand over objects from one thread to another, you don't need
to worry about any JMM stuff in the pojo's to transfer as long as
there is a safe handover.

This also is the reason why Spring beans don't suffer from visibility
and reordering problems as long as the setters on pojo's are not
called after bean creation :)

>
> If I'm on the right track though then I'm very happy about that.
>
> On 30 Jun 2009, at 13:25, Peter Veentjer wrote:
>
>>> It seems to me that immutability for the sake of propagating constructor
>>> changes to main memory
>>> is something of a misnomer - this is more about using the 'final' keyword
>>> as
>>> a coarse grained hook into the
>>> java memory model. Maybe if we had more direct access to that memory
>>> model
>>> then we could ensure
>>> that mutable objects could safely be constructed as well, for example:
>>>
>>> public class MyMutableClass {
>>>  private String myNonFinal;
>>>
>>>  public MyClass() {
>>>     this.myNonFinal = "hello world";
>>>     MemoryModel.flush(); // flush-commit similar to other cache
>>> technologies
>>>  }
>>> }
>>
>> I don't see a happens before relation between the write of the
>> myNonFinal example and the usage. So I don't think this example is
>> going to work.
>>
>>> So my suggestion is that sometimes we rely on the side effects of 'final'
>>> to
>>> help with safe publication rather
>>> than expressing a desire to express immutable semantics. The only way I
>>> can
>>> see to gain the best of both
>>> worlds is to use java atomics, which I can declare final but whose
>>> contents
>>> I can modify.
>>>
>>
>> If you use a handover (so from thread1 to thread2, without the object
>> being touched by the thread1 after handover) you need some kind of
>> mechanism to safely handover the reference (for example a volatile or
>> Atomic class). But actions also ensures that all writes done  in
>> thread1 prior to the handover, are visible after the handover in
>> thread1. In JCiP this is called 'piggybacking on synchronisation'.
>>
>> so
>>
>> class Person{String name;}
>>
>> volatile Person global;
>>
>> //thread1
>> void foo(){
>>  Person p = new Person();
>>  p.name ="peter";
>>  global = p;
>> }
>>
>> //thread2
>> void bar(){
>>  Person p = global;
>>  if(p!=null){print(p.name);}
>> }
>>
>> So you don't need to litter your code with all kinds of JMM cruft.
>
>



More information about the Concurrency-interest mailing list