Требуется пояснение для синхронизированного ключевого слова - PullRequest
1 голос
/ 07 августа 2020

Я изучаю многопоточность в Java. Я немного смущен тем, как потоки обращаются к методам с использованием ключевого слова synchronized, поскольку я нахожу противоречивые руководства о том, как и какие потоки могут получить к ним доступ. Итак, просто чтобы поделиться своими текущими знаниями:

  • Каждый объект, который мы создаем, имеет связанный с ним монитор / блокировку
  • Каждый раз, когда поток обращается к синхронизированному методу, он должен иметь блокировку объекта / экземпляра, который он пытается вызвать
  • Поток может снять sh блокировку с помощью метода wait () в синхронизированном блоке.
  • Как только поток вызывает notify / notifyAll, он пробуждает потоки, которые вызывали метод wait ().

Итак, я сделал фиктивную программу, чтобы выделить то, что мне было любопытно, поскольку я получал смешанные ответы в обучающих материалах (если только я этого не сделал) не понимаю правильно) ..

Main:

public class Main {

public static void main(String[] args) throws InterruptedException {

    Operation operation = new Operation();

    Thread tOne = new Thread(new OperationProcessor(operation));
    Thread tTwo = new Thread(new OperationProcessor(operation));
    Thread tThree = new Thread(new OperationProcessor(operation));
    Thread tFour = new Thread(() -> {
        for(int i =0 ; i < 500; i ++){
            operation.subtract();
        }
    });

    tOne.start();
    tTwo.start();
    tThree.start();
    tFour.start();

    tOne.join();
    tTwo.join();
    tThree.join();

    System.out.println(operation.counter);
}
}

Operation:

public class Operation {

int counter = 0;

public synchronized void add(){
    System.out.println(Thread.currentThread().getName() + " reading the value: " + counter);
    counter++; //same as counter = counter + 1;
}

public void subtract(){
    System.out.println(Thread.currentThread().getName() + " in the subtract method.");
}
}

Operation Processor:

public class OperationProcessor implements Runnable {
private final Operation operation;

public OperationProcessor(Operation operation) {
    this.operation = operation;
}

@Override
public void run() {
    for (int i = 0; i < 1000; i++) {
        operation.add();
    }
}
}

What I попытался сделать это проверить, могут ли разные потоки вызывать другие несинхронизированные методы ОДНОВРЕМЕННО, как другие потоки, вызывающие другие синхронизированные методы в том же экземпляре объекта? Например, если Thread1-3 по очереди вызывает метод add () (из-за блокировки), может ли Thread 4 вызывать subtract (), в то время как Thread1-3 выполняет метод add ()? Но не уверен, продемонстрировал ли я это в этом коде ... А также, если оба метода add () и subtract () были синхронизированы, означает ли это, что ТОЛЬКО один поток имеет доступ ко всем синхронизированным методам в объекте? Например, поток A находится в методе add (), поток B НЕ МОЖЕТ вызвать метод subtract ()?

1 Ответ

0 голосов
/ 07 августа 2020

если Thread1-3 по очереди вызывают метод add () (из-за блокировки), может ли поток 4 вызывать subtract (), в то время как Thread1-3 выполняет метод add ()?

Да, может. Если вы каким-то образом изменили subtract counter, вы, вероятно, увидите, что конечный результат не такой, как вы ожидали.

если оба метода add () и subtract () были синхронизированы, Означает ли это, что ТОЛЬКО один поток имеет доступ ко всем синхронизированным методам объекта?

Также да. В этом сценарии доступ к двум методам защищен одной и той же блокировкой. Если один поток удерживает блокировку, потому что он выполняет add(), другой поток, который вызывает subtract(), должен ждать.

Например, поток A находится в методе add (), поток B НЕ МОЖЕТ вызвать вычитание () method?

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

...