Synchronized blocks in value constructors
João Mendonça
jf.mend at gmail.com
Mon Sep 25 10:52:07 UTC 2023
Yes, I am aware that declaring a value class with a marker interface such
as "LooselyConsistentValue" does the same thing.
...for being non-atomic is bug-prone.
>
I agree that this is crucial. The two safety advantages I mentioned are
precisely about this.
To reiterate: in my proposal, users must opt-out of atomicity by writing a
synchronized block that does not include all field declarations.
I'm proposing this syntax for these reasons:
- this particular syntax, as far as I know, has not been analyzed yet
- for the advantages I wrote comparing with the current proposal
- I feel like we are in the syntax-bikeshedding-phase of this particular
issue
On Mon, Sep 25, 2023 at 10:39 AM - <liangchenblue at gmail.com> wrote:
> Honestly, I don't understand why you propose this, for synchronized is
> ALREADY the default behavior of Value Classes per JEP 401. By default, all
> fields in a value class are synchronized (non-atomic), so you won't see a
> Range where min > max. The current proposed syntax asks users to opt-in
> into non-atomic (or non-synchronized in your words) for being non-atomic
> is bug-prone.
>
> Chen Liang
>
> On Mon, Sep 25, 2023 at 5:01 PM João Mendonça <jf.mend at gmail.com> wrote:
>
>> 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/3a862786/attachment-0001.htm>
More information about the valhalla-spec-observers
mailing list