3

I'm wondering if a conditional expression is a thread safe operation in Java.
E.g.:

return (mObject != null ? mObject.toString() : "null");  

So, my question is: If two threads can change mObject, is this code thread safe, or does the developer need to handle any race conditions?

Richard Sitze
  • 8,262
  • 3
  • 36
  • 48
Plinio.Santos
  • 1,709
  • 24
  • 31
  • Sounds like you should synchronize the whole method if mObject is mutable and shared. – duffymo Aug 13 '12 at 13:31
  • The short answer, related to the conditional ternary operator you present, is no. Recall that even an affectation like int i = 0 is not "thread-safe" (thus Atomic* classes) – Alexandre Dupriez Aug 13 '12 at 13:40

3 Answers3

7

No, that's absolutely not thread-safe. You could definitely get a NullPointerException here. It's easy to fix, of course:

Object tmp = mObject;
return tmp != null ? tmp.toString() : "null";

Or, even more easily in this particular case:

return String.valueOf(mObject);

EDIT: As noted in comments, if you've really got two threads racing to update a value with no synchronization, that's probably a sign of bigger problems... but I only tried to answer the question you specifically asked.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • isn't it a little too simply? this solution prevents NPE, but isn't it still possible that tmp is null mObject being changed after the copy was made, hence the value returned is not the actually value of mObject – gefei Aug 13 '12 at 13:35
  • 1
    @G.Z. The OP did not say anything about the memory visibility so I think the answer clearly answers the question. – maba Aug 13 '12 at 13:38
  • @G.Z.: Have edited my answer to indicate potential further problems. – Jon Skeet Aug 13 '12 at 13:44
2

No, it's not thread safe, just make a local copy of mObject:

final Object local = mObject;
return (local != null ? local.toString() : "null"); 
assylias
  • 321,522
  • 82
  • 660
  • 783
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
2

The developer needs to make sure they have a consistent view of any field which can be changed.

This might be a solution

Object mObject = this.mObject;
return mObject != null ? mObject.toString() : "null";  

or

return String.valueOf(mObject);

or

return ""+mObject;
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130