Synchronized blocks in value constructors

João Mendonça jf.mend at gmail.com
Mon Sep 25 09:00:37 UTC 2023


Hello Chen,


Thank you very much for your response.
To address the fragility issue you raised, I would modify the new syntax
proposal to:

*** synchronized blocks in value class field declarations. ***

To your very good point on granularity, I think that synchronized blocks
could still be considered more readable than having to segregate fields in
separate value classes and using some other class modifier/keyword to
indicate non-atomicity.
All the other advantages/disadvantages would remain the same.
Your example would become:

value class Container {
    synchronized {int a, b;}
    int c;
    Container(int a, int b, int c) {
         this.a = a;
         this.b = b;
         this.c = c;
    }
}


João Mendonça


On Mon, Sep 25, 2023 at 2:08 AM - <liangchenblue at gmail.com> wrote:

> Hello Joao,
> I believe the synchronized block proposal is fragile and isn't a good hint
> to the VM. Each constructor can declare its own synchronization groups,
> which makes behaviorally-correct optimization harder.
> For your purpose where you only need to declare some of the properties of
> the value class atomically together, you can group those properties in an
> atomic (regular) value class. Then, you can include these regular value
> classes in a non-atomic value class.
>
> Say you have this:
> value class Container {
>     int a, b, c;
>     Container(int a, int b, int c) {
>          synchronized { this.a = a; this.b = b; }
>          this.c = c;
>     }
> }
>
> Why not this instead:
> nonatomic value class Container {
>     value class Constraint {
>         int a, b;
>         Constraint(int a, int b) { this.a = a; this.b = b; }
>     }
>     Constraint ab; int c;
>     Container(int a, int b, int c) {
>          this.ab = new Constraint(a, b);
>          this.c = c;
>     }
> }
>
> Chen Liang
>
> On Mon, Sep 25, 2023 at 8:58 AM João Mendonça <jf.mend at gmail.com> wrote:
>
>> I would like to propose a new syntax to specify that, in a value class,
>> some fields must be assigned atomically together:
>>
>> *** synchronized blocks in value class constructors. ***
>>
>>
>> Advantages:
>>
>>     - granularity - only the specific fields involved in an invariant
>> need to be assigned in the same synchronized block. Multiple blocks can be
>> used for independent invariants. Tearing is allowed between blocks and
>> between fields assigned outside blocks. VMs could take advantage of this to
>> perform optimizations.
>>     - economy - no new keyword/annotation/interface needed.
>>     - compatibility - synchronized blocks are currently illegal in
>> constructors.
>>     - safety - just like with identity classes, the absence of a
>> synchronized block in a constructor means that the whole constructor is
>> synchronized, i.e. all fields are written atomically.
>>     - safety - an empty synchronized block is required to indicate that
>> tearing is allowed between any fields.
>>     - clarity - "A synchronized block of field assignments" is a very
>> intuitive description of the semantics involved, given the meaning of the
>> word "synchronized" in english.
>>
>>
>> Disadvantages:
>>
>>     - aesthetics - an empty synchronized block is required to indicate
>> that tearing is allowed between any fields.
>>     - safety - a user of a value class has no automatic way to be
>> informed of if/where tearing may occur (can be fixed with an update to
>> the generation of java docs).
>>     - clarity - synchronized blocks (§14.18.) have two meanings:
>>         - The old meaning in regular methods: only one thread may be
>> running inside of a block for the object given in the expression clause
>>         - The new meaning in constructors: all assignments in a block
>> are written atomically (no expression clause)
>>
>> Example:
>>
>>     value class Range {
>>         long start, end;
>>         public Range(long start, long end) {
>>             if (start > end) throw new IllegalArgumentException();
>>             synchronized {
>>                 this.start = start;
>>                 this.end = end;
>>             }
>>         }    }
>>
>> Having all fields assigned in the same synchronized block, as above, is equivalent to declaring no synchronized blocks:
>>
>>     value class Range {
>>         long start, end;
>>
>>         public Range(long start, long end) {
>>             if (start > end) throw new IllegalArgumentException();
>>             this.start = start;
>>             this.end = end;
>>         }    }
>>
>>
>> Another example:
>>
>>     value class Point {
>>         double x, y;
>>                 public Point(double x, double y) {
>>             synchronized {}
>>             this.x = x;            this.y = y;
>>         }    }
>>
>>
>>
>> João Mendonça
>>
>>

On Mon, Sep 25, 2023 at 2:08 AM - <liangchenblue at gmail.com> wrote:

> Hello Joao,
> I believe the synchronized block proposal is fragile and isn't a good hint
> to the VM. Each constructor can declare its own synchronization groups,
> which makes behaviorally-correct optimization harder.
> For your purpose where you only need to declare some of the properties of
> the value class atomically together, you can group those properties in an
> atomic (regular) value class. Then, you can include these regular value
> classes in a non-atomic value class.
>
> Say you have this:
> value class Container {
>     int a, b, c;
>     Container(int a, int b, int c) {
>          synchronized { this.a = a; this.b = b; }
>          this.c = c;
>     }
> }
>
> Why not this instead:
> nonatomic value class Container {
>     value class Constraint {
>         int a, b;
>         Constraint(int a, int b) { this.a = a; this.b = b; }
>     }
>     Constraint ab; int c;
>     Container(int a, int b, int c) {
>          this.ab = new Constraint(a, b);
>          this.c = c;
>     }
> }
>
> Chen Liang
>
> On Mon, Sep 25, 2023 at 8:58 AM João Mendonça <jf.mend at gmail.com> wrote:
>
>> I would like to propose a new syntax to specify that, in a value class,
>> some fields must be assigned atomically together:
>>
>> *** synchronized blocks in value class constructors. ***
>>
>>
>> Advantages:
>>
>>     - granularity - only the specific fields involved in an invariant
>> need to be assigned in the same synchronized block. Multiple blocks can be
>> used for independent invariants. Tearing is allowed between blocks and
>> between fields assigned outside blocks. VMs could take advantage of this to
>> perform optimizations.
>>     - economy - no new keyword/annotation/interface needed.
>>     - compatibility - synchronized blocks are currently illegal in
>> constructors.
>>     - safety - just like with identity classes, the absence of a
>> synchronized block in a constructor means that the whole constructor is
>> synchronized, i.e. all fields are written atomically.
>>     - safety - an empty synchronized block is required to indicate that
>> tearing is allowed between any fields.
>>     - clarity - "A synchronized block of field assignments" is a very
>> intuitive description of the semantics involved, given the meaning of the
>> word "synchronized" in english.
>>
>>
>> Disadvantages:
>>
>>     - aesthetics - an empty synchronized block is required to indicate
>> that tearing is allowed between any fields.
>>     - safety - a user of a value class has no automatic way to be
>> informed of if/where tearing may occur (can be fixed with an update to
>> the generation of java docs).
>>     - clarity - synchronized blocks (§14.18.) have two meanings:
>>         - The old meaning in regular methods: only one thread may be
>> running inside of a block for the object given in the expression clause
>>         - The new meaning in constructors: all assignments in a block
>> are written atomically (no expression clause)
>>
>> Example:
>>
>>     value class Range {
>>         long start, end;
>>         public Range(long start, long end) {
>>             if (start > end) throw new IllegalArgumentException();
>>             synchronized {
>>                 this.start = start;
>>                 this.end = end;
>>             }
>>         }    }
>>
>> Having all fields assigned in the same synchronized block, as above, is equivalent to declaring no synchronized blocks:
>>
>>     value class Range {
>>         long start, end;
>>
>>         public Range(long start, long end) {
>>             if (start > end) throw new IllegalArgumentException();
>>             this.start = start;
>>             this.end = end;
>>         }    }
>>
>>
>> Another example:
>>
>>     value class Point {
>>         double x, y;
>>                 public Point(double x, double y) {
>>             synchronized {}
>>             this.x = x;            this.y = y;
>>         }    }
>>
>>
>>
>> João Mendonça
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-spec-observers/attachments/20230925/957c46be/attachment-0001.htm>


More information about the valhalla-spec-observers mailing list