При использовании stati c блокировка объекта не работает? - PullRequest
0 голосов
/ 25 марта 2020

Я новичок в Concurrency, пытаюсь понять синхронизированный блок:

public static int count1 = 0;
public static Object lock1 = new Object();

public static void add(){
        synchronized (lock1) {
            count1++;
        }
}

моя проблема с lock1, он не работает, когда метод начинает печатать цвет, он печатает случайным образом, так что я думаю, что проблема в синхронизированном блоке, потому что я смотрю некоторые уроки об этом, все они говорят, что объект блокировки должен быть установлен c, поэтому никаких помех не происходит, но здесь я этого не вижу, почему?

Это метод, который печатает цвет каждой нити:

public static void compute(){
        String color = null;
        switch (Thread.currentThread().getName()) {
            case "First Count Down":
                color = TextColors.ANSI_YELLOW;
                break;
            case "Second Count Down":
                color = TextColors.ANSI_MAGENTA;
                break;
        }
        for (int i=0;i<100;i++) {
            System.out.println(color + Thread.currentThread().getName() + "is Running");
            //add();
            add();
        }
    }

, и это темы:

public static void main(String[] args) {

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                compute();
            }
        });
        t1.setName("First Count Down");

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                compute();
            }
        });
        t2.setName("Second Count Down");

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

        try{
            t1.join();
            t2.join();

        }catch (InterruptedException io){
            io.printStackTrace();

        }

        System.out.println("Count1 = " + count1 + " Count2 = " + count2);

    }

Извините, если мой Engli sh плохо, я не являюсь носителем языка, заранее спасибо

1 Ответ

0 голосов
/ 25 марта 2020

Прежде всего, я думаю, теперь я понимаю ваш вопрос. Вы пытаетесь распечатать свои строки, не вмешиваясь в строки других потоков.

Чтобы достичь этого, вам нужно «защитить» ту часть кода, которая печатает одну строку, чтобы не получить одновременно распечатывает другую строку из другого потока.

Защита может быть выполнена путем синхронизации этих строк кода.

В настоящее время вы синхронизируете только добавление к этому счетчику.

Ваша блокировка (объект, на который вы блокируете, единственный экземпляр этого нового объекта ()) - stati c, и вы не изменяете его в своем коде, поэтому он должен работать.

public static Object lock1 = new Object();

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

Блокировка означает, что, если какой-либо другой поток выполняет (выполняет) ту же строку кода (начало синхронизированного блока), они не получат выполнение до блокировки нить отказывается от блокировки. Это верно только в том случае, если они держатся и просят тот самый замок. И так как вы используете только тот же новый экземпляр Object (), ваша блокировка должна быть в порядке.

В настоящее время ваш код создан так, что метод add () в основном ожидает, пока один из потоков не начнет отсчет один.

Если вы хотите изменить его, чтобы получать отдельно распечатанные строки, попробуйте синхронизировать «блок строчной печати» следующим образом:

    synchronized (lock1) {
        System.out.println(color + Thread.currentThread().getName() + "is Running");
        add();
    }

И пусть счет не будет синхронизировано.

private static void add(){
    count1++;
}

Это будет работать, но в большинстве случаев вы не хотите оставлять метод add () несинхронизированным. Это может быть выполнено из других потоков, кто знает. Но для вашего случая эти изменения помогут.

...