0

Let the scenario be the following:

I have a volatile String str that is shared between multiple threads. As String is immutable, while we can change the reference str, any Object it is pointing to at any time is read-only.

So now, let's say I have a method in one of my threads that reads in str.
Given the reading in of str is not synchronized, is it guaranteed that the Object the method reads in as str stays the same, even if at some time during execution the reference str is overwritten?

I.e., if a method gets passed a reference, does it save a local copy of it (so that changing the original reference afterwards has no effect on the method)?

Is this statement true for any general immutable object/primitive?

Sudix
  • 350
  • 2
  • 15
  • Two things: the value of `str` itself is not guaranteed. The spec says the opposite: if a field is unsynchronized, then multiple threads can read any value, it is indeterminate. Second: Once a method parameter is passed, the method parameter itself doesn't change, it's always the copy of the value "seen" at the time the method is invoked (of course, the value "seen" by an unsynchronized field is indeterminate, but once the value is read it doesn't spontaneously change.) – markspace Aug 25 '18 at 00:46
  • @markspace In that case, is the modifier volatile not essentially useless? If synchronized is the only method guaranteeing that only one Thread at a time reads the value, then volatile may still return incorrect results, even if there's only read-access happening in the threads? – Sudix Aug 25 '18 at 00:50
  • `volatile` guarantees visibility. Without out it the value of `str` can be almost anything. What you seem to be talking about is mutex -- mutual exclusion -- and yes `volatile` does not provide that. Important to note that the more practical versions of mutex are the `java.util.concurrent` classes. The language itself provides fairly primitive thread safety tools and the API is generally preferred. – markspace Aug 25 '18 at 00:58
  • @markspace I am wondering whether I can omit using synchronize as long as I only read a variable without ever changing it. What mark said, i.e. that without synchronize, the value I read is undefined feels weird to me – Sudix Aug 25 '18 at 01:08
  • 2
    It's true though, the language spec requires it so that the parts of your code that don't require synchronization can be aggressively optimized. `long` and `double` are actually worse, as 64 bit fields are allowed to "tear" when written if they're unsyncrhonized. For a value that is written once and then never touched, `volatile` or `final` is best. Use `final` if you can and `volatile` otherwise. – markspace Aug 25 '18 at 01:14
  • 2
    Also, if you want to understand the whole picture, Brian Goetz's book *Java Concurrency in Practice* is by far the best book on Java multi-threading. http://jcip.net/ – markspace Aug 25 '18 at 01:17
  • I agree this is a dupe, but the linked duplicate was only tangentally related. I updated to a different dupe which I think matches the question much better. – Daniel Pryden Aug 25 '18 at 01:41
  • I disagree with @markspace over this statement: "Once a method parameter is passed, the method parameter itself doesn't change, it's always the copy of the value "seen" at the time the method is invoked." It's technically correct (Java always passes arguments by value) but misleading: the object being referred to by an argument can absolutely be modified by another thread while your method is executing -- even parts of the object's constructor may still be executing after your method receives the object as an argument. The concept you need is "safe publication"; see JCIP for details. – Daniel Pryden Aug 25 '18 at 01:49
  • 1
    That said, in the specific case of `java.lang.String` you don't need to worry: String constructors all ensure safe publication. So once you have a reference to a `String` object, you can be sure that it won't change to a different string while you're using it. (Unless someone is doing dirty tricks with reflection, but those can be blocked by a sensible `SecurityManager`.) – Daniel Pryden Aug 25 '18 at 01:52
  • The object a reference points to can change, of course (unless the object is immutable like `String`). But the reference can't (in this case the reference is the value of `str` in the OPs example). So that's what I'm talking about, and what I think the OP was talking about too. As long as a programmer is clear in their own mind what a reference is and what an object, the statement "the method parameter doesn't change" shouldn't create any confusion. – markspace Aug 25 '18 at 01:59

0 Answers0