2013-05-29 3 views
3
public class IntermediateMessage { 

    private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); 
    private final Lock read = readWriteLock.readLock(); 
    private final Lock write = readWriteLock.writeLock(); 

    private volatile double ratio; 

    public IntermediateMessage(){ 
     this.ratio=1.0d; 
    } 

    public IntermediateMessage(double ratio){ 
     this.ratio = ratio; 
    } 

    public double getRatio(){ 
     read.lock(); 
     try{ 
      return this.ratio; 
     } 
     finally{ 
      read.unlock(); 
     } 
    } 

    public void setRatio(double ratio){ 
     write.lock(); 
     try{ 
      this.ratio = ratio; 
     } 
     finally{ 
      write.unlock(); 
     } 
    } 
} 

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

+0

извините. моя вина. Я обновил свой вопрос. Я просто хотел убедиться, что это необходимо, чтобы подать в суд на блокировку чтения/записи с волатильной декларацией. – codereviewanskquestions

ответ

1

Вам вообще нужно блокировать? Скорее всего, нет, согласно ограниченным требованиям, которые вы описали. Но прочитайте это, чтобы быть уверенным ...

  • У вас есть только одна нить.
    • Это означает, что значение переменной никогда не может быть «устаревшим» из-за того, что конкурирующие авторы «сбиваются» друг с другом (без возможного состояния гонки). Таким образом, никакая блокировка не требуется для обеспечения целостности при индивидуальном рассмотрении отдельной переменной.
  • Вы не упомянули, требуется ли какая-либо форма атомной согласованной модификации нескольких переменных. Я предполагаю, что это не так.
    • IF ratio всегда должны быть согласованы с другими переменными (например, в других объектов) - то есть, если множество переменных, необходимо изменить в синхронности как группа ни с кем не читает только часть изменений - тогда замок является требуется для обеспечения согласованности атомов с набором переменных. Затем согласованные переменные должны быть изменены вместе внутри одной фиксированной области, и считыватели должны получить одну и ту же блокировку перед чтением любого из этих наборов переменных (при необходимости ожидая в заблокированном состоянии).
    • ЕСЛИ отношение может быть изменено в любое время, как одинокий переменной и не должны быть совместимы с другими переменными, то не требуется замок дать атомную последовательность к набору переменных.

вам нужен летучий модификатор делать? Ну да!

  • У вас есть несколько потоков чтения.
  • Переменная может меняться в любой момент, включая мгновение до того, как она будет прочитана.
  • Модификатор volatile используется в многопоточных приложениях, чтобы гарантировать, что значение, считанное «читателями», всегда соответствует значению, написанному «писателями».
+0

также, volatile требуется для long/double, потому что они не гарантируются, что они будут записаны атомарно иначе. – jtahlborn

+0

Правильно, но здесь нет проблем. Как уже было сказано, есть один поток писателей. Так что конкурирующая неатомная запись (иначе говоря, «сбивание») не является проблемой. –

+0

проблема не в написании, а в чтении (ака читатель мог увидеть частично обновленное значение). поэтому, да, это актуально здесь. – jtahlborn

1

Вы выполняете чрезмерный перехват синхронизации, что приведет к некоторой неэффективности.

Ключевое слово java «volatile» означает, что переменная не будет кэшироваться и что у нее будет синхронизированный доступ для нескольких потоков.

Итак, вы блокируете переменную, которая по умолчанию синхронизирована.

Таким образом, вы должны либо удалить ключевое слово volatile, либо удалить блокировки реентера. Вероятно, волатильность, так как вы будете более эффективны с несколькими чтениями, как вы сейчас синхронизируете.

0

При условии, что два потока пытаются читать и записывать на одном объекте, и вы хотите, чтобы целостность данных была сохранена. Просто сделайте синхронизацию вашего приемника и сеттера. Когда метод синхронизирован, только один поток может вызвать метод синхронизации. Хотя один поток выполняет один из синхронизированных методов, ни один другой поток не сможет вызвать какой-либо синхронизированный метод. Таким образом, в вашем случае, если у вас есть метод get&, синхронизированный метод, вы можете быть уверены, что поток читает/записывает ни один другой поток не может выполнять чтение/запись.

Надеюсь, это поможет!

1

Для чтения/записи примитивного значения достаточно только volatile.

-1

Сделайте ratio окончательный, и он будет потокобезопасным.

+0

Это не будет сделано. Финал просто означает, что вы не можете изменить определение в подклассах текущего класса. отношение имеет тип int - и не какой-то класс, который должен быть неизменным. статический final сделает его потокобезопасным, но Q конкретно говорит, что отношение должно быть изменчивым. –

+0

Все конечные поля гарантируют безопасность потоков. Это относится к статическим и нестатическим полям. Он не имеет ничего общего с подклассами. –

+0

Спасибо! Скраб упоминание 'static' - на неправильном треке. 'final' сделает' int' неизменным и, следовательно, потокобезопасным. Затем его можно было установить только один раз во время инициализации объекта; 'static final' может быть установлен только один раз во время инициализации класса. Но плакат хочет изменить объект, поэтому 'final' не будет работать. –

Смежные вопросы