3

I was told, that creating a new instance is always an async message; but I don't understand why.

e.g.:

Foo myFoo = new Foo();

Here I will have to wait until the constructor finishes and returns my new object. But doesn't asynchronous mean, that I go on independently (no waiting) - like starting a thread?

Charles Follet
  • 827
  • 1
  • 10
  • 28
fab0l1n
  • 49
  • 3
  • 16
    Creating a new instance in Java is synchronous. Either you got told something wrong or there is a misunderstanding. – Thomas Jul 06 '16 at 12:11
  • A new instance in Java is a synchronous procedure. You can get parallel process with threaded process or lambada expression – Alvaro Silvino Jul 06 '16 at 12:15
  • @Thomas [here](http://stackoverflow.com/questions/27001842/how-to-draw-calls-from-constructors-in-uml-sequence-diagrams) you can see how create is seen as asynchronous. Everyone does this, it's just never explained. – fab0l1n Jul 06 '16 at 13:08
  • 3
    Hmm, in UML sequence diagrams you're normally not bothering with object construction (and often object lifetime is neglected as well, except when it really matters). As the name implies a sequence diagram deals with the sequence of calls and doesn't necessarily mention whether a call is synchronous or not. UML itself is language-independent and thus has to deal with largely asynchronous languages as well (consider Javascript where you'd have to use callbacks to keep execution sequential in certain situations). TL;DR: in sequence diagrams object creation or lifetime often doesn't matter. – Thomas Jul 06 '16 at 13:46
  • 1
    Here's a nice statement from Martin Fowler on interpreting arrowheads in sequence diagrams: "If you’re reading a sequence diagram, beware of making assumptions about synchrony from the arrowheads unless you’re sure that the author is intentionally making the distinction." (taken from [UML Distilled 3rd edition](http://www.agentgroup.unimore.it/~nicola/courses/IngegneriaDelSoftware/uml/books/UMLDistilled.pdf) - page 54). – Thomas Jul 06 '16 at 14:51
  • 1
    Often, downvoters are asked about why they downvoted. Here, I wonder where the upvotes come from. (I didn't downvote either, just wonder what's so special about this question, which seems to be a very basic misunderstanding...) – Marco13 Jul 06 '16 at 16:50

3 Answers3

4

I was told, that creating a new instance is always an async message;

Sorry, I have to say that either you heard it wrong or you were told something that is wrong. But first off, we should get some terminology straight. The term "async" or "asynchronous" means that the invocation returns immediately to the caller. We can easily demonstrate that this is not true with a constructor, with a simple experiment [1]. In other words, the constructor must return for the caller to make any progress.

Starting a thread is indeed asynchronous. The call to Thread.start() returns immediately and at some later point in time the thread actually starts running and executing the run() method.

1 The Experiment

Consider your class (for illustration only) is like below:

Foo.java

class Foo {
    Foo() throws InterruptedException {
        while (true) {
            System.out.println("not returning yet ...");
            Thread.sleep(2000);
        }
    }
    public static void main(String[] args) throws InterruptedException {
         Foo foo = new Foo();
    }
}

If you compiled and run this class (I used Java 8 on my Mac, but that is not a requirement). As expected, this class runs forever producing the output every 2 seconds:

not returning yet ...
not returning yet ...
not returning yet ...
not returning yet ...

Note that the sleep call was added just to make it bearable. You could try this experiment without it, but then your program will overwhelm one of the CPU's by stressing it to 100%.

If, while it is running, you took a thread dump (for example, by using the command jstack), you see something like below (curtailed for brevity):

"main" #1 prio=5 os_prio=31 tid=0x00007f9522803000 nid=0xf07 
waiting on condition [0x000000010408f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
    at java.lang.Thread.sleep(Native Method)
    at Foo.<init>(Foo.java:5)
    at Foo.main(Foo.java:9)

Regardless of the state of the thread (RUNNABLE, BLOCKED, WAITING, TIMED_WAITING), you will always see (take various thread dumps to see what this means) you will always see these two lines:

    at Foo.<init>(Foo.java:5)
    at Foo.main(Foo.java:9)

which means that the caller (in this case, the main thread) will never make any progress. And since this constructor never returns, no progress happens.

Kedar Mhaswade
  • 4,535
  • 2
  • 25
  • 34
0

I was told, that creating a new instance is always an async message;

No, java constructors doesn't have implyed synchronization. Anyway, you can have concurrency issues within it. There is not guarantee that all the fields are initialized after the constructor call.

Here I will have to wait until the constructor finishes and returns my new object. But doesn't asynchronous mean, that I go on independently (no waiting) - like starting a thread?

Nope, you don't have to wait. You can access the object within another thread.

I suggest you to read this thread.

Community
  • 1
  • 1
Charles Follet
  • 827
  • 1
  • 10
  • 28
  • [in this example](http://stackoverflow.com/questions/27001842/how-to-draw-calls-from-constructors-in-uml-sequence-diagrams): inside foo() an instance of B is created - asynchronous -; so foo() will go on without waiting? this would bring some problems if i try to work with this object - lets say, I call b.bar(), b being my new object of B. – fab0l1n Jul 06 '16 at 13:15
  • b will **not** be `null`, so you will be able to call `b.bar()` without throwing a `NullPointerException`. B may be in a possibly semi-initialized state. – Charles Follet Jul 06 '16 at 13:44
  • @fab0l1n what gives you the impression that the instance of B is asynchronously created? In the accepted answer's second diagram you see that `foo()` is only called on `B` after the instance has been created. The distance between the two calls (and the size of the "activity bar" of A) does neither state how much time lies in between the two calls nor that `A#foo()` is doing anything in between. It just states that the method context is still active, i.e. `A#foo()` is running albeit in a waiting/suspended state (it waits for the constructor to return and _then _calls `B#foo()`). – Thomas Jul 06 '16 at 13:53
  • @Thomas An closed arrowhead shows an synchronous message, while an open arrowhead shows an asynchronous. > it waits for the constructor to return and _then _calls B#foo() then it is actually synchronous? – fab0l1n Jul 06 '16 at 14:28
  • "No, java constructors doesn't have implyed synchronization. ... There is not guarantee that all the fields are initialized after the constructor call." - That's basically the opposite of the correct statement. Java constructors *are* always implicitly synchronized: there is no way a constructor of an object can run concurrently, i.e. more than once in the same or another thread. After the constructor call returned, the object *is* completely initialized. – JimmyB Jul 06 '16 at 14:29
  • @CharlesFollet let's say b.bar() depends on an attribute, that's initialised inside the constructor, how can I be sure there won't be problems, if the constructor is called asynchronously and I try to call b.bar right after it inside a.foo()? – fab0l1n Jul 06 '16 at 14:35
  • @fab0l1n I'd suspect that people often don't care about that. After all UML diagrams come in a variety of flavors as people tend to adapt the notation to their organization/needs etc. - In that case if some diagram _could imply_ asynchronous object creation it's highly likely that _it isn't meant to_, – Thomas Jul 06 '16 at 14:36
  • @fab0l1n to answer your last question: you can't call any method on an instance that has not been constructed yet and you don't get a reference to such an instance. Constructors in Java are synchronous after all. The only problem you could run into is trying to call a method inside the constructor which requires access to some not yet initialized fields, but that's a matter of call order - the calls themselves are still synchronous. – Thomas Jul 06 '16 at 14:39
  • well, thanks guys, so the create(-arrow) in sequence diagrams is asynchronous by convention? – fab0l1n Jul 06 '16 at 14:58
  • @JimmyB So this [answer](http://stackoverflow.com/a/12611390/3042945) is wrong? Or am I getting it wrong? – Charles Follet Jul 08 '16 at 14:05
  • @Thomas "you can't call any method on an instance that has not been constructed yet" - Is certainly wrong. As soon as `this` becomes available the object is fully accessible, which is at the very start of the constructor. The constructor *itself* can hand out that `this`, e.g. to another thread, and continue its initialization work while the other thread can already access fields and methods of the half-initialized object. – JimmyB Jul 08 '16 at 14:38
  • @CharlesFollet Not sure. Maybe we're talking about different notions of "synchronized". What I mean is: A constructor can only ever be called exactly *once* for each object. No way to call it a second time, concurrently or not. Yet, the *object* itself is completely accessible to anyone who gets a hold of the object's `this`. Still, the object *is* fully initialized once the constructor call returns. – JimmyB Jul 08 '16 at 14:40
  • @JimmyB that might have been misleading or incomplete. Yes, you could call a method inside a constructor or provide `this` to another thread but the latter would more refer to the problem of synchronization and not synchronous construction (as seen by the calling thread) and in practice you'd do good trying to avoid that - and if the constructor would send `this` to another thread it should definitely be modelled as a message in the sequence diagram. – Thomas Jul 08 '16 at 15:29
0

Example for concurrent access to an object while the constructor is still executing:

public class Demo {

  private volatile int constructionCounter;

  private volatile String string;

  public Demo() throws InterruptedException {

    super();

    assert this.constructionCounter == 0;

    this.constructionCounter++;

    // From this point on, there's no way the constructionCounter can ever be != 1 again, because the constructor will never run more than once, concurrently or otherwise.
    assert this.constructionCounter == 1;

    final Demo newInstance = this;

    Thread t = new Thread( new Runnable() {
        public void run() {
          // Access new instance from another thread.
          // Race condition here; may print "Hello null" or "Hello World" depending on whether or not the constructor already finished.
          System.out.println("Hello " + newInstance.getString());
        }
    });

    t.start();

    this.setString( "World!" );

  }

  public String setString( String str ) {
    this.string = str;
  }

  public String getString() {
    return this.string;
  }
}

Note that this is only ever possible if and when the constructor itself somehow hands this out to another thread.

JimmyB
  • 12,101
  • 2
  • 28
  • 44
  • I fail to see how this will help OP. This situation you describe here hasn't been asked about. – Tom Jul 08 '16 at 14:59
  • @Tom Agreed, this should have been a comment. But the code won't go into a comment. I'm relating to the discussion if a constructor is "synchronized" and if an object can be accessed *before* the constructor returns. – JimmyB Jul 08 '16 at 15:02
  • Specifically, @Thomas said "you can't call any method on an instance that has not been constructed yet", which is not true as my example should show. – JimmyB Jul 08 '16 at 15:03
  • When you wrote this to disprove a comment, then you might should quote that comment in your answer to make it more clearer? It would had helped me, at least :D. – Tom Jul 08 '16 at 15:05