2016-11-04 8 views
1

У меня есть два класса.Синхронизация Java и видимость памяти. Является ли 10 видимым для других потоков?

Один класс - это просто контейнер для целочисленного значения с использованием методов get и set synchronized.

public class Sync { 
    private int dataSync; 

    public synchronized int getDataSync() { 
     return dataSync; 
    } 

    public synchronized void setDataSync(int data) { 
     dataSync = data; 
    } 
} 

Другие классы аналогичны. Это просто контейнер для целочисленного значения с методами get и set без синхронизации.

public class NotSync { 

    private int dataNotSync; 

    public int getDataNotSync() { 
     return dataNotSync; 
    } 

    public void setDataNotSync(int data) { 
     dataNotSync = data; 
    } 
} 

Теперь мой вопрос «является 10 значением гарантированно видимой для всех других потоков» в конце методы выполнения.

public class RunSync { 

    public static void main(String[] args) { 
     RunSync rs = new RunSync(); 
     rs.run(); 
    } 

    private NotSync dataNS; 

    private Sync dataS; 

    private int  data; 

    public RunSync() { 
     dataS = new Sync(); 
     dataNS = new NotSync(); 
    } 

    public synchronized void run() { 
     data = 100; 
     dataS.setDataSync(45); 
     dataNS.setDataNotSync(10); 
     //Question A: is 10 value guaranteed to be visible to all other 
     //threads when method exits? 
     //we are inside a synchronized block aren't we? 
     //so all writes must be flushed to main memory 
    } 
} 

EDIT: Представьте себе, есть другие темы. Это просто быстрый письменный пример. Вопрос идет о том, что точно гарантировано, что он покраснел в основную память, когда заканчивается блок синхронизации.

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

Так что, если другой поток получает блокировку RunSync, он будет гарантированно увидеть 10 в NotSync экземпляре RunSync Даже если NotSync не защищен

EDIT3:? родственный вопрос без окончательного ответа Я все еще ищу. What is the scope of memory flushed or published to various threads when using volatile and synchronized?

EDIT4: Для упрощения примера, что об этом методе из RunSync класса

public synchronized void run2() { 
    dataNS.setDataNotSync(10); 
} 

Когда RUN2 выходов, ничего не гарантировано промывать в основную память? Определенный ответ на это ответит на мой вопрос. Если Нет, это означает, что только члены блокировки гарантированно будут сброшены назад и будут видны другим потокам, если другие потоки получат тот же самый замок в RunSync. Ответ - нет гарантии.

EDIT5: и в этом случае утверждается, что это правда?

public class RunSync { 

public volatile boolean was10Written = false; 

    public synchronized void run2() { 
     dataNS.setDataNotSync(10); 
     was10Written = true; 
    } 

    public void insideAnotherThread() { 
     if(was10Written) { 
     int value = dataNS.getDataNotSync(); 
     assert value == 10; 
     } 
    } 
} 
+3

Почему ваш вопрос риторический? –

+0

Это видно другим темам, которые синхронизируются на чем-то перед чтением. –

+0

@Matt Timmermans риторический, потому что это всего лишь пример. Что именно сбрасывается в основную память при синхронизации выходов? только члены замка? Не их содержание? – Mordan

ответ

1

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

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

Это верно, если запись одного потока происходит до действия синхронизации. Запись в 10 происходит после и, как таковая, нет гарантий видимости.

Если у вас есть новое поле и напишите ему как 10, прежде чем писать до dataSync (синхронизировано), и вы оцениваете dataSync как 45, то это будет видно в новом поле.

+0

Фактический ответ «возможно», а не «нет»;) –

+0

Я должен сказать, что не гарантировано быть видимым, спасибо за исправление :) –

+0

, когда setDataNotSync завершает работу. Я абсолютно согласен. – Mordan

0

Какие еще темы? В любом случае вы должны увидеть ключевое слово volatile для начала. Также синхронизация одного метода не синхронизирует переменную экземпляра для чтения/записи. Таким образом, если один поток пишет, другой может считывать другое значение, так как только методы синхронизируются (только один поток за раз устанавливает значение, а один читает, но вы можете иметь как чтение/запись на то же самое время

+0

это был риторический вопрос. представьте, что есть другие темы. это был всего лишь пример, чтобы показать проблему. – Mordan