Concurrency question.

292 views
Skip to first unread message

Grzegorz Gierlach

unread,
Mar 3, 2017, 4:51:04 AM3/3/17
to mechanical-sympathy
It passes on x86 however for some reason I'm not 100% sure it is a correct implementation. Is there a better way of doing it?

@JCStressTest
@State
@Outcome(id = "1, 0", expect = ACCEPTABLE, desc = "first executed")
@Outcome(id = "0, 1", expect = ACCEPTABLE, desc = "second executed")
@Outcome(id = "1, 1", expect = FORBIDDEN, desc = "both executed!")
@Outcome(id = "0, 0", expect = FORBIDDEN, desc = "none executed!")
public class VolatileConcurrencyTest {

   
volatile Object receiver;

   
volatile Object resolution;

   
AtomicBoolean applied = new AtomicBoolean();

   
@Actor
    void actor1(IntResult2 r) {
       
receiver = new Object();
       
if (resolution != null && applied.compareAndSet(false, true)) {
            r
.r1 = 1;
       
} else {
            r
.r1 = 0;
       
}
   
}

   
@Actor
    void actor2(IntResult2 r) {
       
resolution = new Object();
       
if (receiver != null && applied.compareAndSet(false, true)) {
            r
.r2 = 1;
       
} else {
            r
.r2 = 0;
       
}
   
}
}


Aleksey Shipilev

unread,
Mar 3, 2017, 5:42:12 AM3/3/17
to mechanica...@googlegroups.com
On 03/03/2017 10:51 AM, Grzegorz Gierlach wrote:
> It passes on x86 however for some reason I'm not 100% sure it is a correct
> implementation. Is there a better way of doing it?

The discussion about "correct", "way of doing it" is irrelevant if you don't
describe what is your intent with this test.

But mechanically, this is a Dekker test in disguise:

http://hg.openjdk.java.net/code-tools/jcstress/file/tip/tests-custom/src/main/java/org/openjdk/jcstress/tests/volatiles/DekkerTest.java

The only forbidden state is (0, 0) in plain old Dekker. It stands to reason that
gating the 0->1 transition with CAS makes (1, 1) forbidden too. So your test
should pass, modulo runtime and hardware bugs.

> @JCStressTest
>
> @State
> @Outcome(id ="1, 0",expect =ACCEPTABLE,desc ="first executed")
> @Outcome(id ="0, 1",expect =ACCEPTABLE,desc ="second executed")
> @Outcome(id ="1, 1",expect =FORBIDDEN,desc ="both executed!")
> @Outcome(id ="0, 0",expect =FORBIDDEN,desc ="none executed!")
> publicclassVolatileConcurrencyTest{
>
> volatileObjectreceiver;
>
> volatileObjectresolution;
>
> AtomicBooleanapplied =newAtomicBoolean();
>
> @Actor
> voidactor1(IntResult2r){
> receiver =newObject();
> if(resolution !=null&&applied.compareAndSet(false,true)){
> r.r1 =1;
> }else{
> r.r1 =0;
> }
> }
>
> @Actor
> voidactor2(IntResult2r){
> resolution =newObject();
> if(receiver !=null&&applied.compareAndSet(false,true)){
> r.r2 =1;
> }else{
> r.r2 =0;
> }
> }
> }

-Aleksey



signature.asc

Grzegorz Gierlach

unread,
Mar 3, 2017, 5:59:24 AM3/3/17
to mechanical-sympathy
I'm sorry for not being clear.
The idea behind the test is to have a 'Promise' where resolution should be applied to receiver exactly once. Of course both receiver and resolution can be set from any thread at any time.
I see that having (0, 0) forbidden and 'applied' preventing (1, 1) it should work.

Thank you Aleksey

Grzegorz Gierlach

unread,
Mar 3, 2017, 10:39:39 AM3/3/17
to mechanical-sympathy
Should have stumpled upon it earlier https://shipilev.net/blog/2014/jmm-pragmatics/ ;)


On Friday, 3 March 2017 10:51:04 UTC+1, Grzegorz Gierlach wrote:
Reply all
Reply to author
Forward
0 new messages