0

This code came from sample OCP/SCJP

I'm not really sure why Printx() is called before run(). and why this is guaranteed?

public class ConstructorOrRun extends Thread {

    private int x = 2;

    public ConstructorOrRun() throws Exception {
        x = 5;
        start();
    }

    public void printX() throws Exception {
        x = x - 1;
        System.out.print(x);
    }

    public void run() {
        x *= 2;
    }

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        new ConstructorOrRun().printX();

    }

}
user3431327
  • 135
  • 4
  • 14
  • 2
    `extends Thread` is horrible practice, unless your intent is to change how threading works. Stop that. – cHao Oct 30 '14 at 02:32
  • Nathan Hughes' "it would be bad form" answer is a bit of an understatement. You can not rely on testing to determine whether a program is "thread safe" or not. Testing on one OS version won't tell you whether it will work on a different OS version. Testing in one JRE version won't tell you whether it will work on a different JRE version, and testing today may not tell you whether or not it will work tomorrow. If the correctness of a program depends on the outcome of a race (e.g., like the race to set x in your example), then the program is wrong no matter what testing says. – Solomon Slow Oct 30 '14 at 14:07

2 Answers2

4

I don't think 'guaranteed' is the right word here. In practice the printx will be likely to finish first, because starting a new thread takes a huge amount of time relative to the time taken for the current running thread to do a litle arithmetic, get the (uncontended) lock for the console and write to it.

It is a race condition, though, and it would be a really bad idea to rely on either thing happening first. If a program runs enough times all kinds of interleavings may happen. There's no guarantee which thing will happen first here, it would be better to avoid making assumptions.

There's another issue. The constructor is called by the main thread, initializing x, then starting a new thread. The new thread modifies x in the run method, but there isn't anything requiring making the contents of x visible to the new thread. Making x volatile would make its contents visible.

And yet another issue: the arithmetic operations take multiple steps to be executed and can be interfered with by the other thread. It's not just a question of which operation will happen first, they could be interleaved. Fixing this would require locking or using atomicInteger.

Community
  • 1
  • 1
Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • @user3431327: i don't know where you got this, but the questions test specific objectives, it's not apparent to me what those would be here. – Nathan Hughes Oct 31 '14 at 02:03
3

ConstructorOrRun() returns immediately, on the main thread, and then printX() is invoked.

There's no guarantee that calling start() in the constructor will cause run() to start, let alone finish (on a different thread), before the constructor returns. In fact, I'd be surprised if it did.

GreyBeardedGeek
  • 29,460
  • 2
  • 47
  • 67