开发者

Java Synchronization Problems

I am just starting to learn about Java concurrency and I am getting some strange output from the following code:

ThreadSafe.java:

public class ThreadSafe {
    private int value;

    public ThreadSafe() {
        value = 0;
    }

    public synchronized int getNext() {
        if (value >= 10000) {
            value = 0;
        }
        return value++;
    }
}

RunnableImpl.java:

public class RunnableImpl implements Runnable {
    private String name;
    private ThreadSafe ts;

  开发者_Python百科  public RunnableImpl(String name, ThreadSafe ts) {
        this.name = name;
        this.ts = ts;
    }

    @Override
    public void run() {
        while (true) {
            System.out.println(name + ": " + ts.getNext());
        }
    }
}

Main.java:

public class Main {
    public static void main(String[] args) {
        ThreadSafe ts = new ThreadSafe();

        Runnable a = new RunnableImpl("A", ts);
        Runnable b = new RunnableImpl("B", ts);

        new Thread(a).start();
        new Thread(b).start();
    }
}

Whenever the threads switch off, I get output like the following:

B: 7320
B: 7321
A: 4278 // What?
A: 7323
A: 7324

Going back up the output where A and B switch off:

A: 4275
A: 4276
A: 4277
B: 2279 // ROBBLE ROBBLE!
B: 4279
B: 4280

I can see that A left off at 4277 earlier on and picked up at 4278 before skipping 7322 and continuing on with 7323. This happens with both value++ and ++value. My understanding was that synchronized would let each thread's method invocation of getNext() complete before letting any other threads execute that method.

When I use private volatile int value; in threadsafe.java I get output similar to the following:

A: 8511
A: 8512
A: 8513
B: 7022 // Meh.
B: 8514
B: 8515

This time no numbers were skipped (from ++value, still skips with value++) but the output still seems to be using a cached value for the first go.

What am I overlooking here?


Your ThreadSafe class is fine. This is happening most probably because of the thread scheduling. Namely, in the first example, thread "A" got de-scheduled after fetching 4278 from the instance, but before printing it to the terminal.

Then "B" ran for a while, fetching all values up to 7322, and printing all values up to 7321 before being de-scheduled, at which point "A" was scheduled again, and its next step was to print the value it had previously fetched (4278), and the continuing with the next value from the ThreadSafe class (7323).

So your problem is that while fetching the numbers is properly thread-safe, printing them is not.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜