Home > Enterprise >  Threads can't get the access to shareable resource in Java
Threads can't get the access to shareable resource in Java

Time:03-02

I can't get to understand why the shared list in Consumers is always empty while the Provider adds values to it. I have the Provider:

class Provider extends Thread {
    List<Integer> products;
    Random rnd = new Random();

    public Provider(List<Integer> products) {
        this.products = products;
    }

    @Override
    public void run() {
        //Provider just generate random value and adds the value to the shared list
        for (int i = 0; i < 10; i  ) {
            Integer product = rnd.nextInt(100);
            System.out.println("added value: " product);
            products.add(product);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

And the the Consumer:

class Consumer extends Thread {
    List<Integer> products;

    public Consumer(List<Integer> products) {
        this.products = products;
    }

    @Override
    public void run() {
        System.out.println("Consumer started");
        for (int i = 0; i < 5;) {
            //Consumer just removes elements from shared list five times
            if (!products.isEmpty()) {
                Integer product = products.remove(0);
                System.out.println("removed: " product);
                i  ;
            }
        }
        System.out.println("Consumer stopped");
    }
}

In the main I have the following:

List<Integer> products = new ArrayList<>();
new Provider(products).start();
new Consumer(products).start();
new Consumer(products).start();

I supposed each Consumer should read five values from shareable list after the Provider adds values to it, but in the Consumers the list is always empty. Why the list isn't being updated?

I get the following result:

Consumer started
Consumer started
added value: 13
removed: 13
removed: 13
added value: 28
added value: 53
added value: 32
added value: 85
added value: 23
added value: 60
added value: 10
added value: 15
added value: 85

After the Provider has finished the Consumers are working but can't remove any item because of the condition.

Please don't write about synchronisation. I understand that the threads should synchronize the access to common resource. But it's study example and my goal is to make the Consumers read and remove the values from list.

CodePudding user response:

I think the first comment hits the nail on the head. Without any synchronization then the threads are not guaranteed to see an update. Especially with a tight loop like that.

Adding synchronized to the consumer works for me.

class Consumer extends Thread {
    List<Integer> products;

    public Consumer(List<Integer> products) {
        this.products = products;
    }

    @Override
    public void run() {
        System.out.println("Consumer started");
        for (int i = 0; i < 5;) {
            //Consumer just removes elements from shared list five times
            synchronized(products){
                if (!products.isEmpty()) {
                    Integer product = products.remove(0);
                    System.out.println("removed: " product);
                    i  ;
                }
            }
        }
        System.out.println("Consumer stopped");
    }
}

When I tried this without synchronization the consumers never take from the list.

  • Related