Если я не синхронизирую методы, что происходит в фоновом режиме, из-за чего приложение запускается, пока консоль ничего не печатает? - PullRequest
3 голосов
/ 09 мая 2020

У меня есть основной класс с двумя потоками. Эти два потока запускают два метода, определенных в другом классе.

WaitNotifyMain. java

package com.practice.multithreading;

public class WaitNotifyMain {

    public static void main(String[] args) {
        WaitNotify waitNotify = new WaitNotify();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    waitNotify.produce();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        // lambda expressions Java 8
        Thread t2 = new Thread(() -> {
            try {
                waitNotify.consume();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


    }

}

WaitNotify. java

package com.practice.multithreading;

import java.util.LinkedList;
import java.util.List;

public class WaitNotify {


    /*created an object of linkedlist without Polymorphism  as we require 
    removeFIrst() method which is specific to the linkedList class*/
    private LinkedList<Integer> list = new LinkedList<Integer>();

    private final int LIMIT=10;

    public void produce() throws InterruptedException{
        int value = 0;
        while(true) {

            while(list.size()!=LIMIT) {
            list.add(value++);
            System.out.println("Added an element");

            }

        }

    }

    public void consume() throws InterruptedException{

        while(true) {
            while(!list.isEmpty()) {
                System.out.print("List size :"+list.size());
                int value = list.removeFirst();
                System.out.println("; value is: " +value);

            }

        }
    }
}

Вывод

Added an element
Added an element
Added an element
Added an element
Added an element
Added an element
Added an element
Added an element
Added an element
Added an element
List size :1Added an element
; value is: 0
List size :10Added an element
; value is: 1
List size :10Added an element
; value is: 2
List size :10Added an element
; value is: 3
List size :10Added an element
; value is: 4
List size :10Added an element
; value is: 5
List size :10Added an element
; value is: 6
List size :10Added an element
; value is: 7
List size :10Added an element
; value is: 8
List size :10Added an element
; value is: 9
List size :10Added an element
; value is: 10
List size :10Added an element
; value is: 11
List size :10Added an element
; value is: 12
List size :10; value is: 13
List size :10; value is: 14
List size :9; value is: 15
List size :8; value is: 16
List size :7; value is: 17
List size :6; value is: 18
List size :5; value is: 19
List size :4Added an element
Added an element
Added an element
Added an element
Added an element
Added an element
Added an element
Added an element
; value is: 20
List size :10; value is: 21
List size :10; value is: 22
List size :9; value is: 23
List size :8; value is: 24
List size :7; value is: 25
List size :6; value is: 26
List size :5; value is: 27
List size :4; value is: 28
List size :3; value is: 29
List size :2; value is: 30
List size :1; value is: 31
Added an element
Added an element
Added an element
Added an element
Added an element
Added an element
Added an element
Added an element
Added an element
Added an element
Added an element
List size :1Added an element
; value is: 32
List size :10Added an element
; value is: 33
List size :10Added an element
; value is: 34
List size :10Added an element
; value is: 35
List size :10Added an element
; value is: 36
List size :10; value is: 37
List size :10Added an element
Added an element
; value is: 38
List size :10Added an element
; value is: 39
List size :10Added an element
; value is: 40
List size :10Added an element
; value is: 41
List size :10Added an element
; value is: 42
List size :10Added an element
; value is: 43
List size :10Added an element
; value is: 44
List size :10Added an element
; value is: 45
List size :10Added an element
; value is: 46
List size :10Added an element
; value is: 47
List size :10Added an element
; value is: 48
List size :10Added an element
; value is: 49
List size :10Added an element
; value is: 50
List size :10Added an element
; value is: 51
List size :10Added an element
; value is: 52
List size :10Added an element
; value is: 53
List size :10Added an element
; value is: 54
List size :10Added an element
; value is: 55
List size :10Added an element
; value is: 56
List size :10Added an element
; value is: 57
List size :10Added an element
; value is: 58
List size :10Added an element
; value is: 59
List size :10Added an element
; value is: 60
List size :10Added an element
; value is: 61
List size :10Added an element
; value is: 62
List size :10Added an element
; value is: 63
List size :10Added an element
; value is: 64
List size :10Added an element
; value is: 65
List size :10Added an element
; value is: 66
List size :10Added an element
; value is: 67
List size :10Added an element
; value is: 68
List size :10Added an element
; value is: 69
List size :10Added an element
; value is: 70
List size :10Added an element
; value is: 71
List size :10Added an element
; value is: 72
List size :10Added an element
; value is: 73
List size :10Added an element
; value is: 74
List size :10Added an element
; value is: 75
List size :10Added an element
; value is: 76
List size :10Added an element
; value is: 77
List size :10Added an element
; value is: 78
List size :10Added an element
; value is: 79
List size :10Added an element
; value is: 80
List size :10Added an element
; value is: 81
List size :10Added an element
; value is: 82
List size :10Added an element
; value is: 83
List size :10Added an element
; value is: 84
List size :10Added an element
; value is: 85
List size :10Added an element
; value is: 86
List size :10Added an element
; value is: 87
List size :10Added an element
; value is: 88
List size :10Added an element
; value is: 89
List size :10Added an element
; value is: 90
List size :10Added an element
; value is: 91
List size :10Added an element
; value is: 92
List size :10Added an element
; value is: 93
List size :10Added an element
; value is: 94
List size :10Added an element
; value is: 95
List size :10; value is: 96
List size :10; value is: 97
List size :9; value is: 98
List size :8; value is: 99
List size :7Added an element
Added an element
Added an element
Added an element
Added an element
; value is: 100
List size :10; value is: 101
List size :9; value is: 102
List size :8; value is: 103
List size :7; value is: 104
List size :6; value is: 105
List size :5; value is: 106
List size :4; value is: 107
List size :3; value is: 108
List size :2; value is: 109
List size :1; value is: 110

>>>>>>>after this nothing in console<<<<<<<<<<<<<

Я понимаю, что поскольку он не синхронизируется, он работает не так, как ожидалось, и я получаю выходные данные diff каждый раз при запуске.

Но мой вопрос в том, почему консоль показывает, что мое приложение до сих пор не запущено, а я не вижу никаких выходных данных в консоли.

Может кто-нибудь объяснить такое поведение?

Я испробовал еще несколько вещей: если поместить Thread.sleep() внутри внешних циклов, он продолжит печатать в консоли бесконечно, а если я поставлю syso во внешние циклы, то я также получу вывод в консоли на неопределенный срок.

Что это за странное поведение.

Ответы [ 2 ]

3 голосов
/ 09 мая 2020

Добавьте вывод в оба цикла while(true), и вы увидите, что один из потоков завис, возможно, другой поток не получает время кванта.

1 голос
/ 10 мая 2020

JVM в какой-то момент будет кешировать размер списка - который является основой для list.size() и list.isEmpty() - в каждом потоке, на сколько это возможно.

Без какого-либо блока synchronized «столько, сколько можно» будет бесконечно.

Если производитель не синхронизирован, в какой-то момент он будет кэшировать list.size() == 10 и не будет входить внутренний l oop, и не будет создавать никаких новых значений для потребителя.

Если потребитель не синхронизирован, в какой-то момент он будет кэшировать list.size() == 0 и не будет вводить внутренний l oop, и не будет очищать пространство из списка, чтобы позволить производителю производить.

Так что на самом деле вы получите это зависание, даже если вы synchronized только производитель или только потребитель .

Когда вы добавляете что-то вроде Thread.sleep() или System.out.println(), вы просите JVM выполнить операцию, которая по сути является «внешней», что заставляет JVM обновлять sh кэшированные значения для этого резьба.

...