• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Difference between initializing a variable in a constructor and in a setter method

 
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If I've got




Is this class thread safe ? From my reading I would suggest it was.


But if I've got




This class isn't thread safe.

Why is there a difference between initialising something in a constructor and in a setter ?

Thanks,

Michael


 
Saloon Keeper
Posts: 27762
196
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
When an object is being constructed, it's still in the hands of the JVM's object factory and so the regular application threads can't access it.

Once constructed, however, the object is cast out into threadspace. At that point, if you want to be thread-safe, you have to code for thread safety.

If a constructor invokes a setter from within the constructor method, then the setter code is thread safe since the constructor is operating outside the application thread system. But that same setter will not be thread-safe during normal operation.

And as a side note, since a constructor can access other objects that are already participating in the application threadspace, it should realize that those objects could potentially do horrible things if, for example, the incomplete object is passed to them as a parameter. Then again, they could do horrible things to the object under construction even without threading.
 
Saloon Keeper
Posts: 15510
363
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
There is no difference. Neither is thread-safe.

Consider the following code:

This code may print either of the three following results:

  • 'a' doesn't reference an object
  • 1
  • 0

  • The first option is printed when line 4 executes before line 11. The second option is printed when line 11 executes before line 4 does.

    Now, you might ask how it's possible that this program can also print 0. The reason is that processors are allowed to reorder instructions to make execution more efficient. In theory, it's possible that the thread that executes line 11 assigns the new object reference to the a variable before it initializes the i field in the constructor. The thread that executes the if-statement on line 4 then sees that a is not null, and then calls a.getI(), which will return 0 if it finishes running before the constructor does.

    There's absolutely no difference between constructors and setters here. There's only a difference if you make i final. Besides making it so that the field can't be assigned a value more than once, it has the additional effect that other threads can not access the field before the constructor has finished running. If you make i final, the A class becomes thread-safe and the value 0 will never be printed.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15510
    363
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Tim Holloway wrote:When an object is being constructed, it's still in the hands of the JVM's object factory and so the regular application threads can't access it.


    This is not true. You can get a reference to an uninitialized object if a thread other than the constructing thread can access the variable where the new object will be assigned to, as I demonstrated in my code above.
     
    Tim Holloway
    Saloon Keeper
    Posts: 27762
    196
    Android Eclipse IDE Tomcat Server Redhat Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    OK. You've confused me. Why should line 11 ever be executed before line 4?

    Yes, modern compilers can do a lot of optimising and that includes moving code around. But the line is drawn at the source level. Regardless of what order things do internally, their execution order as statements is not allowed to be altered.

    Furthermore, there are limits even within statements. Otherwise the "short circuit" operators couldn't work reliably.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15510
    363
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Tim Holloway wrote:OK. You've confused me. Why should line 11 ever be executed before line 4?


    Because lines 4 through 8 of the code I've written are exeucted by a different thread, and that thread may reach those lines later than the original thread reaches line 11.

    Regardless of what order things do internally, their execution order as statements is not allowed to be altered.


    Not true. Statements and parts of statements may be executed completely out of order, as long as the reordering doesn't affect the final results of the thread that executes them. No such guarantee is made for other threads.

    Furthermore, there are limits even within statements. Otherwise the "short circuit" operators couldn't work reliably.


    Of course there are limits, I'm not saying that instructions may be reordered willy-nilly. They MAY sometimes be reordered though, and that reordering MAY affect other threads if you don't use memory barriers correctly.

    Note that even when the left hand side of a short-circuiting operator would cause the operator to shortcircuit, the right hand side MAY be executed regardless, due to branch prediction, but this is not visible at the Java level and is a whole different discussion anyway.
     
    Michael Farragher
    Ranch Hand
    Posts: 35
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Hi Stephen,

    Can direct you to Java Concurrency in Practice, pages 50 and 51.

    If you look at class Holder on page 51, that is similar to the first class I listed - an int set in the constructor and then read in another method.

    If you look at the footnote at the bottom of page 50, it says "The problem here is not the Holder class itself ..."
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15510
    363
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I don't have that book, so I'll need more context than what you're giving me.
     
    Rancher
    Posts: 4801
    50
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Stephan van Hulst wrote:
    Consider the following code:



    I take it this is only some scratch code.
    I get complaints that a isn't effectively final (Java 8).

    Any hints what it ought to look like to see the issue?
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15510
    363
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Yes, I wrote it without testing it, apologies. An alternative would be to declare 'a' as a field instead of a local variable.

    Note that if you're going to try to reproduce the case where the code prints 0, the chance is extremely small, and may not even occur at all on some systems.
     
    Dave Tolls
    Rancher
    Posts: 4801
    50
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    No, that's fair enough, I just couldn't see the route to get the null.
    Should have figured it out, as it's similar to the old singleton issue.
     
    reply
      Bookmark Topic Watch Topic
    • New Topic