Suyash
Suyash

Reputation: 2551

Is initialization of objects Thread Safe in Java

I've written similar code to this in one of my applications but I'm not sure whether it is thread safe.

public class MyClass {
    private MyObject myObject = new MyObject();

    public void setObject(MyObject o) {
        myObject = o;
    }

    public MyObject getObject() {
        return myObject;
    }
}

The setObject() and getObject() methods will be called by different threads. The getObject() method is going to be called by a thread that keeps drawing on a Canvas. For optimum FPS and smooth motion, I don't want that thread to be kept waiting for a synchronization lock. Hence, I want to avoid using synchronization unless it is really necessary. So is it really necessary here? Or is there any other better way to solve this problem?

And by the way, it doesn't matter if the thread receives an older copy of the object.

Upvotes: 0

Views: 927

Answers (5)

Marko Topolnik
Marko Topolnik

Reputation: 200296

As for the status of your current version, it is definitely not thread-safe because concurrent access of myObject will establish a data race.

You didn't specify this, but if MyObject is not thread-safe itsef, then your program will not be thread-safe, regardless of what you do to the code you have shown.

it doesn't matter if the thread receives an older copy of the object.

The Java Memory Model allows much worse things than that to happen to objects accessed via a data race:

  • a thread may receive always the same object (the first one it happened to read);
  • a thread may observe the object with only some of the reachable values initialized (a torn object).

For optimum FPS and smooth motion, I don't want that thread to be kept waiting for a synchronization lock.

Have you spent any effort to actually measure how much time your threads are waiting for the lock? My guess: you didn't because that time is so short as to be undetectable.

However, your case doesn't even call for locks: just making your instance variable volatile will be enough to guarantee safe sharing of the object between threads.

Upvotes: 5

dcastro
dcastro

Reputation: 68750

You should make the shared variable volatile, to let a thread know that other threads/processes/etc may change its value.

Beside that, there's no concurrency issue in your code.

The second line, which creates an instance of MyObject when an instance of MyClass is created, is perfectly fine. No one will have access to the shared variable until the instance of MyObject is fully constructed (unless you leak the shared variable from within the constructor).

The setObject method is also fine - all it does is assign an object to the shared variable myObject. And since assignments are atomic, there's nothing to worry about.

Upvotes: 0

m0skit0
m0skit0

Reputation: 25874

Yes, it is thread-safe under the said conditions, so long as you mark myObject as volatile. You will always get a correct MyObject instance from getObject().

Upvotes: 0

Tim B
Tim B

Reputation: 41210

You actually have a number of complications here:

  1. myObject needs to be volatile. (Otherwise other threads may NEVER see changes).

  2. The initial value of myObject will be fully constructed before MyClass is accessed so that is safe in this case, however in general you need to be careful about combining construction of objects and multi threading.

Upvotes: 2

assylias
assylias

Reputation: 328913

No it's not thread safe - this could happen:

  • a thread may not see the latest version of myObject when calling getObject (which you can live with apparently)
  • a thread may never see any updates made to myObject by other threads when calling getObject
  • a thread may see an updated reference to a MyObject that is in a inconsistent state (partially constructed for example)

The easiest way to solve these issues is to mark myObject volatile.

Upvotes: 4

Related Questions