How to simulate constructor race conditions?

后端 未结 4 664
故里飘歌
故里飘歌 2020-12-19 23:03

I am reading \"Java Concurrency in practice\" and looking at the example code on page 51.

This states that if a thread has references to a shared object then other t

相关标签:
4条回答
  • 2020-12-19 23:12

    Well, you need to understand the issues a little more. It isn't really a case of anything being or not being "guaranteed." With concurrency problems, nothing is really guaranteed unless you really do specific things to force the problem to happen. You're just relying on the hope that enough runs should produce, which is not the case. These kinds of problems are hard to predict, which is why concurrency is a hard problem. You could try doing more work in your functions, but I assure you these are real problems that the runtime is not going to save you from.

    0 讨论(0)
  • 2020-12-19 23:17

    You don't publish the reference until after the constructor has finished, change Widgit like this:

    private class Widgit{ // NOTE: Not class is not static anymore
        private int n;
        private int n2;
    
        Widgit(int n) throws InterruptedException{
            this.n = n;
            w = this; // publish reference
            Thread.sleep(2);
            this.n2 = n;
        }
    
        void checkMe(){
            if (n != n2) {
            throw new RuntimeException("World is f*cked");
        }    
    }
    

    Should now throw.

    Edit: You should also declare the Widgit field as volatile:

     private volatile Widgit w;
    
    0 讨论(0)
  • 2020-12-19 23:26

    Before sleeping, start a new thread which prints the value of n2. You will see the second thread can access the object before the constructor has finished.

    The following example demonstrates this on the Sun JVM.

    /* The following prints
    Incomplete initialisation of A{n=1, n2=0}
    After initialisation A{n=1, n2=2}
     */
    public class A {
        final int n;
        final int n2;
        public A() throws InterruptedException {
            n = 1;
            new Thread(new Runnable() {
                public void run() {
                    System.out.println("Incomplete initialisation of " + A.this);
                }
            }).start();
            Thread.sleep(200);
            this.n2 = 2;
        }
        @Override
        public String toString() {
            return "A{" + "n=" + n + ", n2=" + n2 + '}';
        }
        public static void main(String... args) throws InterruptedException {
            System.out.println("After initialisation " + new A());
        }
    }
    
    0 讨论(0)
  • 2020-12-19 23:28

    This will never throw a RunTimeException because your Widgit instance variable w remains null until the constructor code has executed. While your main thread is sleeping in the Widgit constructor, your Checker instance is hitting NullPointerException constantly as the w variable is still null. When your main thread finishes construction, the two int variables in Widgit are equal.

    0 讨论(0)
提交回复
热议问题