Синхронный метод в андроиде

Вы можете подумать, что этот вопрос является дубликатом этого, но никакие ответы на этот вопрос не помогают мне понять synchronized метод в андроиде. Я много искал в Google, чтобы понять методы synchronized, и я нашел ответ, но они не помогли мне полностью понять методы Synchronized, потому что ни один ответ не имеет идеального практического примера.

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

ОБНОВЛЕНИЕ

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

synchronized void add() {
    counter++;
    Log.e("JK", String.valueOf(counter));
}

synchronized void minus() {
    counter--;
    Log.e("JK", String.valueOf(counter));
}

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

new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    synchronized (counter++) {
                        add();
                    }
                }
            },500);
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    minus();
                }
            },1000);

person Jaydip Kalkani    schedule 10.10.2018    source источник
comment
Пожалуйста, сократите свой код до минимально возможного примера, который воспроизводит вашу проблему, и опубликуйте его. Теперь вы просите нас объяснить всю концепцию синхронизации, и она без изменений может быть закрыта как слишком широкая.   -  person Torben    schedule 10.10.2018
comment
хорошо... позвольте мне опубликовать мой код. @Торбен   -  person Jaydip Kalkani    schedule 10.10.2018
comment
@Torben, пожалуйста, взгляните на обновленный вопрос.   -  person Jaydip Kalkani    schedule 10.10.2018
comment
Использование synchronized (counter++) {add();} неверно, метод add уже синхронизирован, не нужно помещать его в синхронизированный блок в runnable. Кроме того, счетчик кажется общим ресурсом, к которому вы не хотите получать доступ из двух потоков одновременно. Это означает, что вы должны изменить его ТОЛЬКО из синхронизированных методов.   -  person GiorgosDev    schedule 10.10.2018


Ответы (2)


Синхронизированный метод — это метод, который может использоваться одновременно только одним потоком. Другие потоки будут ждать, пока метод не будет освобожден. У вас должны быть только серьезные причины, чтобы объявить метод синхронизированным, потому что такой метод снижает производительность. Классический случай использования синхронизированного метода — это когда несколько потоков используют одни и те же ресурсы, т. е. изменяют состояние какого-то объекта, и необходимо убедиться, что только один поток выполняет это одновременно, иначе это вызовет несогласованность. Также не забудьте сделать синхронизированный метод как можно меньшим, в идеале уменьшите его, чтобы он содержал только операции, которые могут манипулировать общими ресурсами.

Например, класс Reporter имеет общий ресурс fileWriter. Записывает в файл несколько сообщений с информацией об авторах.

class Reporter{
    private FileWriter fileWriter;
    public synchronized void addRecord(String author, String message) throws IOException {
        fileWriter.write("\n<<<<<<<<<<>>>>>>>>>>\n");
        fileWriter.write("Message written by:" + author + "\n");
        fileWriter.write("Message content:" + message);
    }

    public Reporter(FileWriter fileWriter) {
        this.fileWriter = fileWriter;
    }
}

Предположим, вы запускаете этот код из двух разных потоков:

Reporter reporter = new Reporter("path/report");
...
Thread thread = new Thread(){
    public void run(){
      reporter.addRecord("John", "Hi");
    }
  }
 thread.start();
Thread thread2 = new Thread(){
    public void run(){
      reporter.addRecord("Bill", "Hello");
    }
  }
 thread2.start();

Результат для синхронизированного метода будет таким:

<<<<<<<<<<>>>>>>>>>>
Message written by:John
Message content:Hi
<<<<<<<<<<>>>>>>>>>>
Message written by:Bill
Message content:Hello

Если метод не синхронизирован, несколько потоков могут одновременно записывать в файл, что может привести к непредсказуемой последовательности в файле, например:

<<<<<<<<<<>>>>>>>>>>
<<<<<<<<<<>>>>>>>>>>
Message written by:John
Message written by:Bill
Message content:Hello
Message content:Hi
person GiorgosDev    schedule 10.10.2018
comment
Спасибо за ваш ценный ответ, но будет лучше, если вы приведете какой-либо пример. - person Jaydip Kalkani; 10.10.2018
comment
Добавлен пример @Jaydip - person GiorgosDev; 10.10.2018
comment
да, вы правы, но как я могу сгенерировать вывод в обоих случаях? - person Jaydip Kalkani; 10.10.2018
comment
обновленный ответ с кодом, запускающим синхронизированный метод, чтобы увидеть разницу, запустите тот же код с синхронизированным объявлением и без него - person GiorgosDev; 10.10.2018

Синхронизированный метод — это метод, который может использоваться одновременно только одним потоком. Другие потоки будут ждать, пока метод не будет освобожден. У вас должны быть только веские причины, чтобы объявить метод синхронизированным, потому что такой метод снижает производительность и производительность.

person Tippu Fisal Sheriff    schedule 13.09.2020