开发者

Safe publication: does first time passing of Object reference to another thread require safe publication idioms?

开发者 https://www.devze.com 2023-03-09 08:09 出处:网络
I have a class C with definition as given below: public Class C implements Runnable { private B ref; public C(B bobj)

I have a class C with definition as given below:

public Class C implements Runnable
{
    private B ref;
    public C(B bobj)
    {
    this.ref = bobj;                 //(0)
    }
}    

public void run()
{
    //read ‘ref’ without using synchronization.  //(4)
    //Will this read of ref see an up-to-date value or stale (may be null) value?
    //do some stuff on ‘ref’ using lock ‘ref’   
}
}

I have a thread T which is already running (e.g. Main thread). Thread T creates an instance of another class B (mutable) e.g.

B b = new B();

Now it constructs an instance of class C and starts the Thread e.g.

C runnable = new C(b);                          // (1)
new Thread(runnable).start();     //(2)

As per Java Language Spec 17.4.4:

An action that starts a thread synchronizes-with the first action in the thread it Starts.

=> statement (2) above synchronizes-with statement (4).

Next section of same spec 17.4.5 says:

If an action x synchronizes-with a following action y, then we also have hb(x, y).

=> here statement (2) happens-before statement (4)

Also, statement (1) which comes before开发者_高级运维 statement (2) can not be re-ordered (otherwise a code in run() of C might detect that)by compiler as (1) comes before (2) in program order (intra-thread semantics). That means, statement (1) will come before (4) in execution order.

My question is whether this way of passing reference (here ‘b’) from one thread to onother is safe?


It is safe in this case.

B b = new B();
C runnable = new C(b);
new Thread(runnable).start();

This code above guarantees that B is constructed and passed to C, and it is all safe etc. What you are not guaranteed is anything post-modification e.g.

new Thread(runnable).start();
b.setSomeStuff(new Stuff());

when run against threaded code:

public void run() {
  Stuff stuff = b.getSomeStuff(); // Can return old or new stuff.
}

Effectively, to answer your question, C cannot be run unless it is constructed completely, which necessitates B existing and being able to be referenced. Problems only occur when you modify stuff in one thread and read it in another while both threads are running.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号