[concurrency-interest] Starting a Thread within a constructor, what can go wrong?

David Holmes davidcholmes at aapt.net.au
Fri Dec 10 20:52:22 EST 2010


Hi Marco,

There are some obviously silly things you can do with this pattern eg:

class DontDoThis {
   Object field1;
   DontDoThis() {
     (new Thread() { public void run() {
          int x = field1.hashcode(); // potential NPE
          ...
      }}).start();
      field1 = new Object();
   }
}

This the classic example of not being thread-safe, or rather of being racy.
The thread can access default initialized object-state.

But if you start the thread at the end of the constructor there is nothing
that can go wrong for this class - there is a happens-before edge between
starting a thread and execution of its run method. So no races and no
visibility issues: all state is fully initialized.

But if you then subclass that "safe" class you could again get racy
behaviour if the run method invokes a virtual method that is overridden in
the subclass and which accesses additional state - which can only be
initialized after the superclass constructor has run.

For the most part though such constructs are not considered good design -
particularly when it comes to threading - because only the simplest of
designs can get away without some form of lifecycle control, for which it is
far better to separate construction of the service from the starting of the
service. There may be additional services that need to be configured before
this service should be started. (Imagine a car that automatically started
the engine as soon as you sat in the drivers seat and closed the door! -
occasionally convenient, but potentially quite hazardous)

Given it is a poor design approach for a service, and it can easily
introduce race conditions, best practice says "don't do this".

HTH

David Holmes

> -----Original Message-----
> From: concurrency-interest-bounces at cs.oswego.edu
> [mailto:concurrency-interest-bounces at cs.oswego.edu]On Behalf Of Marco
> Villalobos
> Sent: Saturday, 11 December 2010 11:30 AM
> To: concurrency-interest at cs.oswego.edu
> Subject: [concurrency-interest] Starting a Thread within a
> constructor,what can go wrong?
>
>
> QUESTION:
>
> Can somebody please give me guidance on how I could possibly create a
> suite of test cases that run in TestNG or JUnit that can prove the
> thread unsafeness of this bad practice?
>
> BACKGROUND
>
> I'm trying to convince my colleague that starting a thread within a
> constructor compromises thread safety.
>
> I understand that, "publishing objects before they are fully
> constructed can compromise thread safety."
>
> But I would like an elaboration on how it compromises thread safety?
>
> I understand that publishing the "this" reference would break
> encapsulation, allowing other classes and threads to potentially
> change the state of my object in an unthread safe manner.
>
> But more specifically, what are the side affects of an object not
> being fully constructed, yet published through a thread.start in a
> constructor.
>
> Here is an example of how "not to do things".
>
> public class DontDoThis {
>
>   public synchronized void mutateMe() {
>       // ... I'm mutating this...
>   }
>
>   public final Thread t;
>
>   public DontDoThis() {
>       t = new Thread(new Runnable() {
>           public void run() {
>               mutateMe();
>           }
>       });
>       t.start();   //     BAD BAD BAD Don't do this.
>   }
> }
>
> Can somebody please give me guidance on how I could possibly create a
> suite of test cases that run in TestNG or JUnit that can prove the
> thread unsafeness of this bad practice?
>
> I want to make a short presentation on the issue.  If I provide a
> compilable and running test case, that would be amazing :)
>
> -Marco
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>



More information about the Concurrency-interest mailing list