0

This problem has puzzled me for a long time, please help me,thanks. This is my java code.

package com.concurrent.example;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * P683
 */
class CircularSet {
    private int[] array;
    private int len;
    private int index = 0;
    public CircularSet (int size) {
        array = new int[size];
        len = size;
        for (int i = 0; i < size; i++) {
            array[i] = -1;
        }
    }

    public synchronized void add(int i ) {
        array[index] = i;
        index = ++index % len;
    }

    public synchronized boolean contains(int val) {
        for (int i = 0; i < len; i++) {
            if(array[i] == val) {
                return true;
            }
        }
        return false;
    }
}

public class SerialNumberChecker {
    private static final int SIZE = 10;
    private static CircularSet serials = new CircularSet(1000);
    private static ExecutorService exec = Executors.newCachedThreadPool();
    private static int serial;
    static class SerialChecker implements Runnable {
        @Override
        public void run() {
            while(true) {
                //int serial;
                synchronized (serials) {
                     serial = SerialNumberGenerator.nextSerialNumber();
                }
                if (serials.contains(serial)) {
                    System.out.println("Duplicate: " + serial);
                    System.exit(0);
                }
                System.out.println(serial);
                serials.add(serial);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < SIZE; i++) {
            exec.execute(new SerialChecker());
            if (args.length > 0) {
                TimeUnit.SECONDS.sleep(new Integer(args[0]));
                System.out.println("No duplicates detected");
                System.exit(0);
            }
        }
    }
}

It can stop, but when i uncomment //int serial;The result is different,it can't stop.Why does this temporary variable have a different result than the static variable of the external class. Is this the reason of using a thread?

The code of SerialNumberGenerator:

public class SerialNumberGenerator {
    private static volatile int serialNumber = 0;
    public static int nextSerialNumber() {
        return serialNumber ++; //Not thread-safe
    }
}
1
  • 1
    You want to do some reading about static first of all. It looks like you really don't understand what this keyword is doing. Commented Jun 2, 2018 at 6:47

1 Answer 1

1

With private static int serial, all SerialNumberCheckers share the same serial. For example:

  1. Thread1 set serial = 1
  2. Thread2 set serial = 2
  3. Thread1 put 2 into CircularSet.
  4. Thread2 found it duplicate and exit.

However, if you declare another int serial in the run method, It will shadow the private static int serial, which means all threads has its own serial and they will assign & check it. Since the generation of serial is in the synchronized block, there will be no duplicates.

Sign up to request clarification or add additional context in comments.

2 Comments

I know what you say, but the result of this code synchronized (serials) { serial = SerialNumberGenerator.nextSerialNumber(); } should get only one value. When i comment //int serial; ,why it can repeat.
@bfq Yeah, SerialNumberGenerator will not return duplicate value. But, different threads are manipulating one the same serial. Just consider the execution order I gave in the answer. And notice, Thread1 can get the value set by Thread2 since the serial is static.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.