2014-10-07 2 views
0

Из некоторых источников ИнтернетаСинхронные методы экземпляра в Java

Вот синхронизированный метод экземпляра:

public synchronized void add(int value){ 

    this.count += value; 
} 

Обратите внимание на использовании синхронизированного ключевого слова в объявлении метода. Это говорит Java, что метод синхронизирован. Синхронный метод экземпляра в Java синхронизируется на экземпляре (объекте), владеющем этим методом. Таким образом, каждый экземпляр синхронизирует свои синхронные методы на другом объекте: экземпляр-владелец. Только один поток может выполняться внутри синхронизированного метода экземпляра. Если существует более одного экземпляра, тогда один поток за раз может выполнять внутри синхронизированного метода экземпляра для каждого экземпляра. Один поток на экземпляр.

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

Случай 1: У меня есть два потока, каждый из которых имеет же экземпляр класса, содержащего метод добавления, то только один из них сможет выполнить описанный выше метод добавления за раз. Следовательно, если один поток вызывает add, тогда он НЕ МОЖЕТ быть предварительно освобожден до того, как он завершит выполнение?

Случай 2: Если обе мои нити имеют два различных экземпляров класса, содержащего метод добавления, то синхронизация не играет никакой роли в этом случае. Оба из них будут выполняться, как если бы синхронизация вообще не применялась.

Правильно ли я в своем понимании?

+0

да, вы получили его. Но имейте в виду, что для case1 другой поток может изменить 'count' из другого метода. (возможно, 'add2'). Вы также можете синхронизировать доступ к ресурсам, используя выражение' synchronized (property) {} '. – dognose

ответ

1

Да, однако

, то он не может быть предварительно опорожнить до завершения исполнения?

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

как если бы синхронизация вообще не применялась.

Разница в том, что без synchronized было бы намного быстрее. Поскольку это такая простая операция. Если вы делаете что-то менее тривиальное, стоимость синхронизации будет относительно небольшой. В любом случае, правильность важна, чем скорость практически во всех случаях.

+0

Ох хорошо. поэтому он может быть предварительно удален, но если другой поток пытается вызвать ту же функцию, добавьте, то это не произойдет. Спасибо. –

+0

Не уверен, что я бы сказал, что код «намного быстрее» без синхронизации. Я бы сказал «несколько быстрее». Современные JVM действительно оптимизировали синхронизацию. – user949300

+0

@ user949300 У них есть и для большинства случаев использования это мало чем отличается, если только операция тривиальна, например '+ =', и в этом случае синхронизация намного дороже. Конечно, правильность важнее скорости. –

0

Ваше понимание в основном правильное. (см. ответ Питера).

Вот (глупый) пример для разработки.

public class Person { 
    private String firstName = "?"; // set an initial value 
    private String lastName = "?"; 

    public void setName(String first, String last) { 
     this.firstName = first; 
     this.lastName = last; 
    } 

    public String toString() { 
     return firstName + " " + lastName ; 
    } 
} 

Так как ни один из методов синхронизации, если один поток вызова setName("John", "Doe") в то же время другой звонит toString(), это возможно для setName быть предварительно опорожнить в середине, так и для ToString() для вызова, причем имя должно быть только «наполовину». Итак, toString() может печатать «Джон?».

Если оба метода синхронизированы, то вызов будет происходить toString() либо полностью перед или полностью после, вызов setName()». Если setName() был выгружен посередине, toString() будет ждать завершения setName. Итак, toString() либо напечатает "??" или «Джон Доу».

Синхронизация может также потребоваться для модели памяти Java, чтобы убедиться, что изменения, сделанные в одном потоке, видны другим потоком. Но это становится более продвинутым ...

+0

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

+1

Исправить. В этом примере этот конкретный экземпляр Person предоставляет блокировку. Если другой экземпляр Человека только что женился и изменился с «Джейн», «Смит» на «Джейн», «Смит-Джонс», это не повлияло бы на блокировку экземпляра John Doe. – user949300