Java: Make all fields either final or volatile?












22














If I have an object which is shared between threads, it seems to me that every field should be either final or volatile, with the following reasoning:




  • if the field should be changed (point to another object, update the primitive value), then the field should be volatile so that all other threads operate on the new value. Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.


  • if the field should never change, make it final.



However, I could not find anything about this, so I wonder whether this logic is flawed or just too obvious?



EDIT of course instead of volatile one might use a final AtomicReference or similar.



EDIT for example, see Is getter method an alternative to volatile in Java?



EDIT to avoid confusions: This question is about cache invalidation! If two threads operate on the same object, the fields of the objects can be cached (per thread), if they are not declared volatile. How can I guarantee that the cache is invalidated properly?



FINAL EDIT Thanks to @Peter Lawrey who pointed me to JLS §17 (Java memory model). As far as I see, it states that synchronization establishes a happens-before relation between operations, so that a thread sees the updates from another thread if those updates "happened-before", e.g. if getter and setter for a non-volatile field are synchronized.










share|improve this question




















  • 5




    Merely a synchronization on the methods which access said field is insufficient - no, synchronization is "stronger" than volatile. It means you won't even enter the method if another thread is in it, so you only enter after the other one exited and finished changing the value.
    – daniu
    Dec 12 '18 at 8:19










  • the problem is that each thread can have its own cached version, so that thread 2 still may see the old version after thread 1 has updated it. tutorials.jenkov.com/java-concurrency/volatile.html
    – Moritz
    Dec 12 '18 at 8:58










  • No, when properly using private fields, so that all access has to be done via synchronized methods, the visibility of the most recent values is already guaranteed. As @daniu correctly pointed out, it will be even stronger than declaring a variable volatile. As the article you’ve linked points out, volatile is not always enough.
    – Holger
    Dec 12 '18 at 15:09






  • 3




    The notion that "volatile" is about "cache invalidation" is bad reasoning; it presupposes a specific memory model implementation, namely that memory is implemented with processor caches that copy the real memory, or that variables are implemented with registers that cache values. Reason about correctness within the abstract memory model that Java gives you, not any particular implementation of it.
    – Eric Lippert
    Dec 12 '18 at 18:35








  • 2




    To that point: volatile is not magic dust that you sprinkle on your program and threading issues go away. Volatile reads and writes may still be re-ordered with respect to each other, and this can still produce unexpected race conditions. Do not allow volatile fields to give you an unearned sense of security about the correctness of your program. Again, you need to reason about the correctness of the program in the context of the memory model of the language.
    – Eric Lippert
    Dec 12 '18 at 18:37
















22














If I have an object which is shared between threads, it seems to me that every field should be either final or volatile, with the following reasoning:




  • if the field should be changed (point to another object, update the primitive value), then the field should be volatile so that all other threads operate on the new value. Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.


  • if the field should never change, make it final.



However, I could not find anything about this, so I wonder whether this logic is flawed or just too obvious?



EDIT of course instead of volatile one might use a final AtomicReference or similar.



EDIT for example, see Is getter method an alternative to volatile in Java?



EDIT to avoid confusions: This question is about cache invalidation! If two threads operate on the same object, the fields of the objects can be cached (per thread), if they are not declared volatile. How can I guarantee that the cache is invalidated properly?



FINAL EDIT Thanks to @Peter Lawrey who pointed me to JLS §17 (Java memory model). As far as I see, it states that synchronization establishes a happens-before relation between operations, so that a thread sees the updates from another thread if those updates "happened-before", e.g. if getter and setter for a non-volatile field are synchronized.










share|improve this question




















  • 5




    Merely a synchronization on the methods which access said field is insufficient - no, synchronization is "stronger" than volatile. It means you won't even enter the method if another thread is in it, so you only enter after the other one exited and finished changing the value.
    – daniu
    Dec 12 '18 at 8:19










  • the problem is that each thread can have its own cached version, so that thread 2 still may see the old version after thread 1 has updated it. tutorials.jenkov.com/java-concurrency/volatile.html
    – Moritz
    Dec 12 '18 at 8:58










  • No, when properly using private fields, so that all access has to be done via synchronized methods, the visibility of the most recent values is already guaranteed. As @daniu correctly pointed out, it will be even stronger than declaring a variable volatile. As the article you’ve linked points out, volatile is not always enough.
    – Holger
    Dec 12 '18 at 15:09






  • 3




    The notion that "volatile" is about "cache invalidation" is bad reasoning; it presupposes a specific memory model implementation, namely that memory is implemented with processor caches that copy the real memory, or that variables are implemented with registers that cache values. Reason about correctness within the abstract memory model that Java gives you, not any particular implementation of it.
    – Eric Lippert
    Dec 12 '18 at 18:35








  • 2




    To that point: volatile is not magic dust that you sprinkle on your program and threading issues go away. Volatile reads and writes may still be re-ordered with respect to each other, and this can still produce unexpected race conditions. Do not allow volatile fields to give you an unearned sense of security about the correctness of your program. Again, you need to reason about the correctness of the program in the context of the memory model of the language.
    – Eric Lippert
    Dec 12 '18 at 18:37














22












22








22


5





If I have an object which is shared between threads, it seems to me that every field should be either final or volatile, with the following reasoning:




  • if the field should be changed (point to another object, update the primitive value), then the field should be volatile so that all other threads operate on the new value. Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.


  • if the field should never change, make it final.



However, I could not find anything about this, so I wonder whether this logic is flawed or just too obvious?



EDIT of course instead of volatile one might use a final AtomicReference or similar.



EDIT for example, see Is getter method an alternative to volatile in Java?



EDIT to avoid confusions: This question is about cache invalidation! If two threads operate on the same object, the fields of the objects can be cached (per thread), if they are not declared volatile. How can I guarantee that the cache is invalidated properly?



FINAL EDIT Thanks to @Peter Lawrey who pointed me to JLS §17 (Java memory model). As far as I see, it states that synchronization establishes a happens-before relation between operations, so that a thread sees the updates from another thread if those updates "happened-before", e.g. if getter and setter for a non-volatile field are synchronized.










share|improve this question















If I have an object which is shared between threads, it seems to me that every field should be either final or volatile, with the following reasoning:




  • if the field should be changed (point to another object, update the primitive value), then the field should be volatile so that all other threads operate on the new value. Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.


  • if the field should never change, make it final.



However, I could not find anything about this, so I wonder whether this logic is flawed or just too obvious?



EDIT of course instead of volatile one might use a final AtomicReference or similar.



EDIT for example, see Is getter method an alternative to volatile in Java?



EDIT to avoid confusions: This question is about cache invalidation! If two threads operate on the same object, the fields of the objects can be cached (per thread), if they are not declared volatile. How can I guarantee that the cache is invalidated properly?



FINAL EDIT Thanks to @Peter Lawrey who pointed me to JLS §17 (Java memory model). As far as I see, it states that synchronization establishes a happens-before relation between operations, so that a thread sees the updates from another thread if those updates "happened-before", e.g. if getter and setter for a non-volatile field are synchronized.







java multithreading volatile final






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 12 '18 at 9:43

























asked Dec 12 '18 at 8:12









Moritz

391112




391112








  • 5




    Merely a synchronization on the methods which access said field is insufficient - no, synchronization is "stronger" than volatile. It means you won't even enter the method if another thread is in it, so you only enter after the other one exited and finished changing the value.
    – daniu
    Dec 12 '18 at 8:19










  • the problem is that each thread can have its own cached version, so that thread 2 still may see the old version after thread 1 has updated it. tutorials.jenkov.com/java-concurrency/volatile.html
    – Moritz
    Dec 12 '18 at 8:58










  • No, when properly using private fields, so that all access has to be done via synchronized methods, the visibility of the most recent values is already guaranteed. As @daniu correctly pointed out, it will be even stronger than declaring a variable volatile. As the article you’ve linked points out, volatile is not always enough.
    – Holger
    Dec 12 '18 at 15:09






  • 3




    The notion that "volatile" is about "cache invalidation" is bad reasoning; it presupposes a specific memory model implementation, namely that memory is implemented with processor caches that copy the real memory, or that variables are implemented with registers that cache values. Reason about correctness within the abstract memory model that Java gives you, not any particular implementation of it.
    – Eric Lippert
    Dec 12 '18 at 18:35








  • 2




    To that point: volatile is not magic dust that you sprinkle on your program and threading issues go away. Volatile reads and writes may still be re-ordered with respect to each other, and this can still produce unexpected race conditions. Do not allow volatile fields to give you an unearned sense of security about the correctness of your program. Again, you need to reason about the correctness of the program in the context of the memory model of the language.
    – Eric Lippert
    Dec 12 '18 at 18:37














  • 5




    Merely a synchronization on the methods which access said field is insufficient - no, synchronization is "stronger" than volatile. It means you won't even enter the method if another thread is in it, so you only enter after the other one exited and finished changing the value.
    – daniu
    Dec 12 '18 at 8:19










  • the problem is that each thread can have its own cached version, so that thread 2 still may see the old version after thread 1 has updated it. tutorials.jenkov.com/java-concurrency/volatile.html
    – Moritz
    Dec 12 '18 at 8:58










  • No, when properly using private fields, so that all access has to be done via synchronized methods, the visibility of the most recent values is already guaranteed. As @daniu correctly pointed out, it will be even stronger than declaring a variable volatile. As the article you’ve linked points out, volatile is not always enough.
    – Holger
    Dec 12 '18 at 15:09






  • 3




    The notion that "volatile" is about "cache invalidation" is bad reasoning; it presupposes a specific memory model implementation, namely that memory is implemented with processor caches that copy the real memory, or that variables are implemented with registers that cache values. Reason about correctness within the abstract memory model that Java gives you, not any particular implementation of it.
    – Eric Lippert
    Dec 12 '18 at 18:35








  • 2




    To that point: volatile is not magic dust that you sprinkle on your program and threading issues go away. Volatile reads and writes may still be re-ordered with respect to each other, and this can still produce unexpected race conditions. Do not allow volatile fields to give you an unearned sense of security about the correctness of your program. Again, you need to reason about the correctness of the program in the context of the memory model of the language.
    – Eric Lippert
    Dec 12 '18 at 18:37








5




5




Merely a synchronization on the methods which access said field is insufficient - no, synchronization is "stronger" than volatile. It means you won't even enter the method if another thread is in it, so you only enter after the other one exited and finished changing the value.
– daniu
Dec 12 '18 at 8:19




Merely a synchronization on the methods which access said field is insufficient - no, synchronization is "stronger" than volatile. It means you won't even enter the method if another thread is in it, so you only enter after the other one exited and finished changing the value.
– daniu
Dec 12 '18 at 8:19












the problem is that each thread can have its own cached version, so that thread 2 still may see the old version after thread 1 has updated it. tutorials.jenkov.com/java-concurrency/volatile.html
– Moritz
Dec 12 '18 at 8:58




the problem is that each thread can have its own cached version, so that thread 2 still may see the old version after thread 1 has updated it. tutorials.jenkov.com/java-concurrency/volatile.html
– Moritz
Dec 12 '18 at 8:58












No, when properly using private fields, so that all access has to be done via synchronized methods, the visibility of the most recent values is already guaranteed. As @daniu correctly pointed out, it will be even stronger than declaring a variable volatile. As the article you’ve linked points out, volatile is not always enough.
– Holger
Dec 12 '18 at 15:09




No, when properly using private fields, so that all access has to be done via synchronized methods, the visibility of the most recent values is already guaranteed. As @daniu correctly pointed out, it will be even stronger than declaring a variable volatile. As the article you’ve linked points out, volatile is not always enough.
– Holger
Dec 12 '18 at 15:09




3




3




The notion that "volatile" is about "cache invalidation" is bad reasoning; it presupposes a specific memory model implementation, namely that memory is implemented with processor caches that copy the real memory, or that variables are implemented with registers that cache values. Reason about correctness within the abstract memory model that Java gives you, not any particular implementation of it.
– Eric Lippert
Dec 12 '18 at 18:35






The notion that "volatile" is about "cache invalidation" is bad reasoning; it presupposes a specific memory model implementation, namely that memory is implemented with processor caches that copy the real memory, or that variables are implemented with registers that cache values. Reason about correctness within the abstract memory model that Java gives you, not any particular implementation of it.
– Eric Lippert
Dec 12 '18 at 18:35






2




2




To that point: volatile is not magic dust that you sprinkle on your program and threading issues go away. Volatile reads and writes may still be re-ordered with respect to each other, and this can still produce unexpected race conditions. Do not allow volatile fields to give you an unearned sense of security about the correctness of your program. Again, you need to reason about the correctness of the program in the context of the memory model of the language.
– Eric Lippert
Dec 12 '18 at 18:37




To that point: volatile is not magic dust that you sprinkle on your program and threading issues go away. Volatile reads and writes may still be re-ordered with respect to each other, and this can still produce unexpected race conditions. Do not allow volatile fields to give you an unearned sense of security about the correctness of your program. Again, you need to reason about the correctness of the program in the context of the memory model of the language.
– Eric Lippert
Dec 12 '18 at 18:37












3 Answers
3






active

oldest

votes


















29














While I feel private final should probably have been the default for fields and variables with a keyword like var making it mutable, using volatile when you don't need it is




  • much slower, often around 10x slower.

  • usually doesn't give you the thread safety you need, but can make finding such bugs harder by making them less likely to appear.

  • unlike final which improves clarity by saying this shouldn't be altered, using volatile when it is not needed, is likely to be confusing as the reader tries to work out why it was made volatile.



if the field should be changed (point to another object, update the primitive value), then the field should be volatile so that all other threads operate on the new value.




While this is fine for reads, consider this trivial case.



volatile int x;

x++;


This isn't thread-safe. As it's the same as



int x2 = x;
x2 = x2 + 1; // multiple threads could be executing on the same value at this point.
x = x2;


What is worse is that using volatile would make this kind of bug harder to find.



As yshavit point's out, updating multiple fields is harder to work around with volatile e.g. HashMap.put(a, b) updates multiple references.




Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.




synchronized gives you all the memory guarantees of volatile and more, which is why it's significantly slower.



NOTE: Just synchronized-ing every method isn't always enough either. StringBuffer has every method synchronized but is worst than useless in a multi-threaded context as it's use is likely to be error-prone.



It's too easy to assume that achieving thread safety is like sprinkling fairy dust, add some magic thread safety and your bugs go away. The problem is that thread safety is more like a bucket with many holes. Plug the biggest holes and the bugs can appear to go away, but unless you plug them all, you don't have thread safety, but it can be harder to find.



In terms of synchronzied vs volatile, this states




Other mechanisms, such as reads and writes of volatile variables and the use of classes in the java.util.concurrent package, provide alternative ways of synchronization.




https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html






share|improve this answer























  • Can you please explain why, given that thread1 and thread2 hold a reference to the same object, and access is via synchronized methods only, thread 2 sees the updates of thread 1 guaranteed? I refer to e.g. tutorials.jenkov.com/java-concurrency/volatile.html This and other resources say (as far as I understand) that the fields can still be cached in different cache lines - that is, thread 2 just has to wait for the getX() to enter but it will still return the cached version. Is there any guarantee that the thread's cache is updated after obtaining the monitor or the like?
    – Moritz
    Dec 12 '18 at 9:03






  • 3




    @Moritz synchronization would be pointless without memory barriers to provide those guarantees. While the value is cached within the synchronized block, it will return the latest value on read and ensure anything written is visible to all threads.
    – Peter Lawrey
    Dec 12 '18 at 9:06












  • makes totally sense to me, but do you by chance know any point let's say in JLS where this is stated?
    – Moritz
    Dec 12 '18 at 9:07






  • 1




    As far as I see, from JLS §17 it follows that if accessor methods are synchronized, this introduces a happens-before relation between the accesses, and thus the second operation will see the update. Right?
    – Moritz
    Dec 12 '18 at 9:35






  • 1




    This is a good answer, but I would suggest a quick note that classes often use state from multiple fields, which volatile can't address. This is similar to your x++ case, but even less subtle, and even harder to work around (ie, you don't get "oh that's easy, just use an AtomicInteger").
    – yshavit
    Dec 12 '18 at 17:59



















7














Making fields you don't need to change final is a good idea, irrespective of threading concerns. It makes instances of the class easier to reason about, because you can know what state it is in more easily.



In terms of making the other fields volatile:




Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.




You would only see a cached value if you accessing the value outside a synchronized block.



All accesses would need to be correctly synchronized. The end of one synchronized block is guaranteed to happen before the start of another synchronized block (when synchronizing on the same monitor).



There are at least a couple of cases where you would still need to use synchronization:




  • You would want to use synchronization if you had to read and then update one or more fields atomically.


    • You may be able to avoid synchronization for certain single field updates, e.g. if you can use an Atomic* class instead of a "plain old field"; but even for a single field update, you could still require exclusive access (e.g. adding one element to a list whilst removing another).



  • Also, volatile/final may be insufficient for non-thread safe values, like an ArrayList or an array.






share|improve this answer































    1














    If an object is shared between threads, you have two clear options:



    1. Make that object read only



    So, updates (or cache) have no impact.



    2. Synchronize on object itself



    Cache invalidation is hard. Very hard. So if you need to guarantee no stale values, you should protect that value and protect the lock around said value.



    Make the lock and values as private on shared object, so the operations here are a implementation detail.



    To avoid dead locks, this operations should be as "atomic", as in to avoid interact with other any lock.






    share|improve this answer





















      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53738662%2fjava-make-all-fields-either-final-or-volatile%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      29














      While I feel private final should probably have been the default for fields and variables with a keyword like var making it mutable, using volatile when you don't need it is




      • much slower, often around 10x slower.

      • usually doesn't give you the thread safety you need, but can make finding such bugs harder by making them less likely to appear.

      • unlike final which improves clarity by saying this shouldn't be altered, using volatile when it is not needed, is likely to be confusing as the reader tries to work out why it was made volatile.



      if the field should be changed (point to another object, update the primitive value), then the field should be volatile so that all other threads operate on the new value.




      While this is fine for reads, consider this trivial case.



      volatile int x;

      x++;


      This isn't thread-safe. As it's the same as



      int x2 = x;
      x2 = x2 + 1; // multiple threads could be executing on the same value at this point.
      x = x2;


      What is worse is that using volatile would make this kind of bug harder to find.



      As yshavit point's out, updating multiple fields is harder to work around with volatile e.g. HashMap.put(a, b) updates multiple references.




      Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.




      synchronized gives you all the memory guarantees of volatile and more, which is why it's significantly slower.



      NOTE: Just synchronized-ing every method isn't always enough either. StringBuffer has every method synchronized but is worst than useless in a multi-threaded context as it's use is likely to be error-prone.



      It's too easy to assume that achieving thread safety is like sprinkling fairy dust, add some magic thread safety and your bugs go away. The problem is that thread safety is more like a bucket with many holes. Plug the biggest holes and the bugs can appear to go away, but unless you plug them all, you don't have thread safety, but it can be harder to find.



      In terms of synchronzied vs volatile, this states




      Other mechanisms, such as reads and writes of volatile variables and the use of classes in the java.util.concurrent package, provide alternative ways of synchronization.




      https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html






      share|improve this answer























      • Can you please explain why, given that thread1 and thread2 hold a reference to the same object, and access is via synchronized methods only, thread 2 sees the updates of thread 1 guaranteed? I refer to e.g. tutorials.jenkov.com/java-concurrency/volatile.html This and other resources say (as far as I understand) that the fields can still be cached in different cache lines - that is, thread 2 just has to wait for the getX() to enter but it will still return the cached version. Is there any guarantee that the thread's cache is updated after obtaining the monitor or the like?
        – Moritz
        Dec 12 '18 at 9:03






      • 3




        @Moritz synchronization would be pointless without memory barriers to provide those guarantees. While the value is cached within the synchronized block, it will return the latest value on read and ensure anything written is visible to all threads.
        – Peter Lawrey
        Dec 12 '18 at 9:06












      • makes totally sense to me, but do you by chance know any point let's say in JLS where this is stated?
        – Moritz
        Dec 12 '18 at 9:07






      • 1




        As far as I see, from JLS §17 it follows that if accessor methods are synchronized, this introduces a happens-before relation between the accesses, and thus the second operation will see the update. Right?
        – Moritz
        Dec 12 '18 at 9:35






      • 1




        This is a good answer, but I would suggest a quick note that classes often use state from multiple fields, which volatile can't address. This is similar to your x++ case, but even less subtle, and even harder to work around (ie, you don't get "oh that's easy, just use an AtomicInteger").
        – yshavit
        Dec 12 '18 at 17:59
















      29














      While I feel private final should probably have been the default for fields and variables with a keyword like var making it mutable, using volatile when you don't need it is




      • much slower, often around 10x slower.

      • usually doesn't give you the thread safety you need, but can make finding such bugs harder by making them less likely to appear.

      • unlike final which improves clarity by saying this shouldn't be altered, using volatile when it is not needed, is likely to be confusing as the reader tries to work out why it was made volatile.



      if the field should be changed (point to another object, update the primitive value), then the field should be volatile so that all other threads operate on the new value.




      While this is fine for reads, consider this trivial case.



      volatile int x;

      x++;


      This isn't thread-safe. As it's the same as



      int x2 = x;
      x2 = x2 + 1; // multiple threads could be executing on the same value at this point.
      x = x2;


      What is worse is that using volatile would make this kind of bug harder to find.



      As yshavit point's out, updating multiple fields is harder to work around with volatile e.g. HashMap.put(a, b) updates multiple references.




      Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.




      synchronized gives you all the memory guarantees of volatile and more, which is why it's significantly slower.



      NOTE: Just synchronized-ing every method isn't always enough either. StringBuffer has every method synchronized but is worst than useless in a multi-threaded context as it's use is likely to be error-prone.



      It's too easy to assume that achieving thread safety is like sprinkling fairy dust, add some magic thread safety and your bugs go away. The problem is that thread safety is more like a bucket with many holes. Plug the biggest holes and the bugs can appear to go away, but unless you plug them all, you don't have thread safety, but it can be harder to find.



      In terms of synchronzied vs volatile, this states




      Other mechanisms, such as reads and writes of volatile variables and the use of classes in the java.util.concurrent package, provide alternative ways of synchronization.




      https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html






      share|improve this answer























      • Can you please explain why, given that thread1 and thread2 hold a reference to the same object, and access is via synchronized methods only, thread 2 sees the updates of thread 1 guaranteed? I refer to e.g. tutorials.jenkov.com/java-concurrency/volatile.html This and other resources say (as far as I understand) that the fields can still be cached in different cache lines - that is, thread 2 just has to wait for the getX() to enter but it will still return the cached version. Is there any guarantee that the thread's cache is updated after obtaining the monitor or the like?
        – Moritz
        Dec 12 '18 at 9:03






      • 3




        @Moritz synchronization would be pointless without memory barriers to provide those guarantees. While the value is cached within the synchronized block, it will return the latest value on read and ensure anything written is visible to all threads.
        – Peter Lawrey
        Dec 12 '18 at 9:06












      • makes totally sense to me, but do you by chance know any point let's say in JLS where this is stated?
        – Moritz
        Dec 12 '18 at 9:07






      • 1




        As far as I see, from JLS §17 it follows that if accessor methods are synchronized, this introduces a happens-before relation between the accesses, and thus the second operation will see the update. Right?
        – Moritz
        Dec 12 '18 at 9:35






      • 1




        This is a good answer, but I would suggest a quick note that classes often use state from multiple fields, which volatile can't address. This is similar to your x++ case, but even less subtle, and even harder to work around (ie, you don't get "oh that's easy, just use an AtomicInteger").
        – yshavit
        Dec 12 '18 at 17:59














      29












      29








      29






      While I feel private final should probably have been the default for fields and variables with a keyword like var making it mutable, using volatile when you don't need it is




      • much slower, often around 10x slower.

      • usually doesn't give you the thread safety you need, but can make finding such bugs harder by making them less likely to appear.

      • unlike final which improves clarity by saying this shouldn't be altered, using volatile when it is not needed, is likely to be confusing as the reader tries to work out why it was made volatile.



      if the field should be changed (point to another object, update the primitive value), then the field should be volatile so that all other threads operate on the new value.




      While this is fine for reads, consider this trivial case.



      volatile int x;

      x++;


      This isn't thread-safe. As it's the same as



      int x2 = x;
      x2 = x2 + 1; // multiple threads could be executing on the same value at this point.
      x = x2;


      What is worse is that using volatile would make this kind of bug harder to find.



      As yshavit point's out, updating multiple fields is harder to work around with volatile e.g. HashMap.put(a, b) updates multiple references.




      Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.




      synchronized gives you all the memory guarantees of volatile and more, which is why it's significantly slower.



      NOTE: Just synchronized-ing every method isn't always enough either. StringBuffer has every method synchronized but is worst than useless in a multi-threaded context as it's use is likely to be error-prone.



      It's too easy to assume that achieving thread safety is like sprinkling fairy dust, add some magic thread safety and your bugs go away. The problem is that thread safety is more like a bucket with many holes. Plug the biggest holes and the bugs can appear to go away, but unless you plug them all, you don't have thread safety, but it can be harder to find.



      In terms of synchronzied vs volatile, this states




      Other mechanisms, such as reads and writes of volatile variables and the use of classes in the java.util.concurrent package, provide alternative ways of synchronization.




      https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html






      share|improve this answer














      While I feel private final should probably have been the default for fields and variables with a keyword like var making it mutable, using volatile when you don't need it is




      • much slower, often around 10x slower.

      • usually doesn't give you the thread safety you need, but can make finding such bugs harder by making them less likely to appear.

      • unlike final which improves clarity by saying this shouldn't be altered, using volatile when it is not needed, is likely to be confusing as the reader tries to work out why it was made volatile.



      if the field should be changed (point to another object, update the primitive value), then the field should be volatile so that all other threads operate on the new value.




      While this is fine for reads, consider this trivial case.



      volatile int x;

      x++;


      This isn't thread-safe. As it's the same as



      int x2 = x;
      x2 = x2 + 1; // multiple threads could be executing on the same value at this point.
      x = x2;


      What is worse is that using volatile would make this kind of bug harder to find.



      As yshavit point's out, updating multiple fields is harder to work around with volatile e.g. HashMap.put(a, b) updates multiple references.




      Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.




      synchronized gives you all the memory guarantees of volatile and more, which is why it's significantly slower.



      NOTE: Just synchronized-ing every method isn't always enough either. StringBuffer has every method synchronized but is worst than useless in a multi-threaded context as it's use is likely to be error-prone.



      It's too easy to assume that achieving thread safety is like sprinkling fairy dust, add some magic thread safety and your bugs go away. The problem is that thread safety is more like a bucket with many holes. Plug the biggest holes and the bugs can appear to go away, but unless you plug them all, you don't have thread safety, but it can be harder to find.



      In terms of synchronzied vs volatile, this states




      Other mechanisms, such as reads and writes of volatile variables and the use of classes in the java.util.concurrent package, provide alternative ways of synchronization.




      https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Dec 12 '18 at 18:57

























      answered Dec 12 '18 at 8:47









      Peter Lawrey

      441k55558959




      441k55558959












      • Can you please explain why, given that thread1 and thread2 hold a reference to the same object, and access is via synchronized methods only, thread 2 sees the updates of thread 1 guaranteed? I refer to e.g. tutorials.jenkov.com/java-concurrency/volatile.html This and other resources say (as far as I understand) that the fields can still be cached in different cache lines - that is, thread 2 just has to wait for the getX() to enter but it will still return the cached version. Is there any guarantee that the thread's cache is updated after obtaining the monitor or the like?
        – Moritz
        Dec 12 '18 at 9:03






      • 3




        @Moritz synchronization would be pointless without memory barriers to provide those guarantees. While the value is cached within the synchronized block, it will return the latest value on read and ensure anything written is visible to all threads.
        – Peter Lawrey
        Dec 12 '18 at 9:06












      • makes totally sense to me, but do you by chance know any point let's say in JLS where this is stated?
        – Moritz
        Dec 12 '18 at 9:07






      • 1




        As far as I see, from JLS §17 it follows that if accessor methods are synchronized, this introduces a happens-before relation between the accesses, and thus the second operation will see the update. Right?
        – Moritz
        Dec 12 '18 at 9:35






      • 1




        This is a good answer, but I would suggest a quick note that classes often use state from multiple fields, which volatile can't address. This is similar to your x++ case, but even less subtle, and even harder to work around (ie, you don't get "oh that's easy, just use an AtomicInteger").
        – yshavit
        Dec 12 '18 at 17:59


















      • Can you please explain why, given that thread1 and thread2 hold a reference to the same object, and access is via synchronized methods only, thread 2 sees the updates of thread 1 guaranteed? I refer to e.g. tutorials.jenkov.com/java-concurrency/volatile.html This and other resources say (as far as I understand) that the fields can still be cached in different cache lines - that is, thread 2 just has to wait for the getX() to enter but it will still return the cached version. Is there any guarantee that the thread's cache is updated after obtaining the monitor or the like?
        – Moritz
        Dec 12 '18 at 9:03






      • 3




        @Moritz synchronization would be pointless without memory barriers to provide those guarantees. While the value is cached within the synchronized block, it will return the latest value on read and ensure anything written is visible to all threads.
        – Peter Lawrey
        Dec 12 '18 at 9:06












      • makes totally sense to me, but do you by chance know any point let's say in JLS where this is stated?
        – Moritz
        Dec 12 '18 at 9:07






      • 1




        As far as I see, from JLS §17 it follows that if accessor methods are synchronized, this introduces a happens-before relation between the accesses, and thus the second operation will see the update. Right?
        – Moritz
        Dec 12 '18 at 9:35






      • 1




        This is a good answer, but I would suggest a quick note that classes often use state from multiple fields, which volatile can't address. This is similar to your x++ case, but even less subtle, and even harder to work around (ie, you don't get "oh that's easy, just use an AtomicInteger").
        – yshavit
        Dec 12 '18 at 17:59
















      Can you please explain why, given that thread1 and thread2 hold a reference to the same object, and access is via synchronized methods only, thread 2 sees the updates of thread 1 guaranteed? I refer to e.g. tutorials.jenkov.com/java-concurrency/volatile.html This and other resources say (as far as I understand) that the fields can still be cached in different cache lines - that is, thread 2 just has to wait for the getX() to enter but it will still return the cached version. Is there any guarantee that the thread's cache is updated after obtaining the monitor or the like?
      – Moritz
      Dec 12 '18 at 9:03




      Can you please explain why, given that thread1 and thread2 hold a reference to the same object, and access is via synchronized methods only, thread 2 sees the updates of thread 1 guaranteed? I refer to e.g. tutorials.jenkov.com/java-concurrency/volatile.html This and other resources say (as far as I understand) that the fields can still be cached in different cache lines - that is, thread 2 just has to wait for the getX() to enter but it will still return the cached version. Is there any guarantee that the thread's cache is updated after obtaining the monitor or the like?
      – Moritz
      Dec 12 '18 at 9:03




      3




      3




      @Moritz synchronization would be pointless without memory barriers to provide those guarantees. While the value is cached within the synchronized block, it will return the latest value on read and ensure anything written is visible to all threads.
      – Peter Lawrey
      Dec 12 '18 at 9:06






      @Moritz synchronization would be pointless without memory barriers to provide those guarantees. While the value is cached within the synchronized block, it will return the latest value on read and ensure anything written is visible to all threads.
      – Peter Lawrey
      Dec 12 '18 at 9:06














      makes totally sense to me, but do you by chance know any point let's say in JLS where this is stated?
      – Moritz
      Dec 12 '18 at 9:07




      makes totally sense to me, but do you by chance know any point let's say in JLS where this is stated?
      – Moritz
      Dec 12 '18 at 9:07




      1




      1




      As far as I see, from JLS §17 it follows that if accessor methods are synchronized, this introduces a happens-before relation between the accesses, and thus the second operation will see the update. Right?
      – Moritz
      Dec 12 '18 at 9:35




      As far as I see, from JLS §17 it follows that if accessor methods are synchronized, this introduces a happens-before relation between the accesses, and thus the second operation will see the update. Right?
      – Moritz
      Dec 12 '18 at 9:35




      1




      1




      This is a good answer, but I would suggest a quick note that classes often use state from multiple fields, which volatile can't address. This is similar to your x++ case, but even less subtle, and even harder to work around (ie, you don't get "oh that's easy, just use an AtomicInteger").
      – yshavit
      Dec 12 '18 at 17:59




      This is a good answer, but I would suggest a quick note that classes often use state from multiple fields, which volatile can't address. This is similar to your x++ case, but even less subtle, and even harder to work around (ie, you don't get "oh that's easy, just use an AtomicInteger").
      – yshavit
      Dec 12 '18 at 17:59













      7














      Making fields you don't need to change final is a good idea, irrespective of threading concerns. It makes instances of the class easier to reason about, because you can know what state it is in more easily.



      In terms of making the other fields volatile:




      Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.




      You would only see a cached value if you accessing the value outside a synchronized block.



      All accesses would need to be correctly synchronized. The end of one synchronized block is guaranteed to happen before the start of another synchronized block (when synchronizing on the same monitor).



      There are at least a couple of cases where you would still need to use synchronization:




      • You would want to use synchronization if you had to read and then update one or more fields atomically.


        • You may be able to avoid synchronization for certain single field updates, e.g. if you can use an Atomic* class instead of a "plain old field"; but even for a single field update, you could still require exclusive access (e.g. adding one element to a list whilst removing another).



      • Also, volatile/final may be insufficient for non-thread safe values, like an ArrayList or an array.






      share|improve this answer




























        7














        Making fields you don't need to change final is a good idea, irrespective of threading concerns. It makes instances of the class easier to reason about, because you can know what state it is in more easily.



        In terms of making the other fields volatile:




        Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.




        You would only see a cached value if you accessing the value outside a synchronized block.



        All accesses would need to be correctly synchronized. The end of one synchronized block is guaranteed to happen before the start of another synchronized block (when synchronizing on the same monitor).



        There are at least a couple of cases where you would still need to use synchronization:




        • You would want to use synchronization if you had to read and then update one or more fields atomically.


          • You may be able to avoid synchronization for certain single field updates, e.g. if you can use an Atomic* class instead of a "plain old field"; but even for a single field update, you could still require exclusive access (e.g. adding one element to a list whilst removing another).



        • Also, volatile/final may be insufficient for non-thread safe values, like an ArrayList or an array.






        share|improve this answer


























          7












          7








          7






          Making fields you don't need to change final is a good idea, irrespective of threading concerns. It makes instances of the class easier to reason about, because you can know what state it is in more easily.



          In terms of making the other fields volatile:




          Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.




          You would only see a cached value if you accessing the value outside a synchronized block.



          All accesses would need to be correctly synchronized. The end of one synchronized block is guaranteed to happen before the start of another synchronized block (when synchronizing on the same monitor).



          There are at least a couple of cases where you would still need to use synchronization:




          • You would want to use synchronization if you had to read and then update one or more fields atomically.


            • You may be able to avoid synchronization for certain single field updates, e.g. if you can use an Atomic* class instead of a "plain old field"; but even for a single field update, you could still require exclusive access (e.g. adding one element to a list whilst removing another).



          • Also, volatile/final may be insufficient for non-thread safe values, like an ArrayList or an array.






          share|improve this answer














          Making fields you don't need to change final is a good idea, irrespective of threading concerns. It makes instances of the class easier to reason about, because you can know what state it is in more easily.



          In terms of making the other fields volatile:




          Merely a synchronization on the methods which access said field is insufficient because they might return a cached value.




          You would only see a cached value if you accessing the value outside a synchronized block.



          All accesses would need to be correctly synchronized. The end of one synchronized block is guaranteed to happen before the start of another synchronized block (when synchronizing on the same monitor).



          There are at least a couple of cases where you would still need to use synchronization:




          • You would want to use synchronization if you had to read and then update one or more fields atomically.


            • You may be able to avoid synchronization for certain single field updates, e.g. if you can use an Atomic* class instead of a "plain old field"; but even for a single field update, you could still require exclusive access (e.g. adding one element to a list whilst removing another).



          • Also, volatile/final may be insufficient for non-thread safe values, like an ArrayList or an array.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Dec 12 '18 at 8:47

























          answered Dec 12 '18 at 8:30









          Andy Turner

          80.1k879133




          80.1k879133























              1














              If an object is shared between threads, you have two clear options:



              1. Make that object read only



              So, updates (or cache) have no impact.



              2. Synchronize on object itself



              Cache invalidation is hard. Very hard. So if you need to guarantee no stale values, you should protect that value and protect the lock around said value.



              Make the lock and values as private on shared object, so the operations here are a implementation detail.



              To avoid dead locks, this operations should be as "atomic", as in to avoid interact with other any lock.






              share|improve this answer


























                1














                If an object is shared between threads, you have two clear options:



                1. Make that object read only



                So, updates (or cache) have no impact.



                2. Synchronize on object itself



                Cache invalidation is hard. Very hard. So if you need to guarantee no stale values, you should protect that value and protect the lock around said value.



                Make the lock and values as private on shared object, so the operations here are a implementation detail.



                To avoid dead locks, this operations should be as "atomic", as in to avoid interact with other any lock.






                share|improve this answer
























                  1












                  1








                  1






                  If an object is shared between threads, you have two clear options:



                  1. Make that object read only



                  So, updates (or cache) have no impact.



                  2. Synchronize on object itself



                  Cache invalidation is hard. Very hard. So if you need to guarantee no stale values, you should protect that value and protect the lock around said value.



                  Make the lock and values as private on shared object, so the operations here are a implementation detail.



                  To avoid dead locks, this operations should be as "atomic", as in to avoid interact with other any lock.






                  share|improve this answer












                  If an object is shared between threads, you have two clear options:



                  1. Make that object read only



                  So, updates (or cache) have no impact.



                  2. Synchronize on object itself



                  Cache invalidation is hard. Very hard. So if you need to guarantee no stale values, you should protect that value and protect the lock around said value.



                  Make the lock and values as private on shared object, so the operations here are a implementation detail.



                  To avoid dead locks, this operations should be as "atomic", as in to avoid interact with other any lock.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Dec 12 '18 at 13:20









                  André LFS Bacci

                  17913




                  17913






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53738662%2fjava-make-all-fields-either-final-or-volatile%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Paul Cézanne

                      UIScrollView CustomStickyHeader Resize height generates problems when scroll is too fast

                      Angular material date-picker (MatDatepicker) auto completes the date on focus out