Как обеспечить в Java атомарного чтения / записи 2 переменных вместе? - PullRequest
4 голосов
/ 10 февраля 2012

В моем классе есть код вроде:

int counter1;
int counter2;

public void method1(){
 if (counter1>0) {
  ...........do something
   if (counter2>0) {
    ....do something else
    }
}

public void method2() {
  counter1=0;
  counter2=0;
}

Мне нужно, чтобы оба счетчика были установлены вместе. Я боюсь, что OS к method1 может быть вызвана только после установки counter1. Возможно ли это? Спасибо.

Ответы [ 3 ]

4 голосов
/ 10 февраля 2012

Либо используйте синхронизированное ключевое слово, как предлагает другой ответ, либо используйте ReentrantReadWriteLock, если у вас больше операций чтения, чем записи в счетчик, для повышения производительности. О замке можно прочитать здесь http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html

private int counter1;
private int counter2;
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();

public void method1(){
   r.lock();
   try { 
     if (counter1>0) {
        ...........do something
     if (counter2>0) {
        ....do something else
     }
   } finally { r.unlock(); }

}

public void method2() {
  w.lock();
  try { 
    counter1=0;
    counter2=0; 
  } finally { w.unlock(); }

}
3 голосов
/ 10 февраля 2012

Конечно, просто используйте синхронизированное ключевое слово :

private final Object LOCK = new Object();
int counter1;
int counter2;

public void method1() {
  synchronized(LOCK) {
     if (counter1>0) {
      ...........do something
       if (counter2>0) {
        ....do something else
       }
    }
}
public void method2() {
  synchronized(LOCK) {
    counter1=0;
    counter2=0;
  }
}

Несколько советов:

Используйте частный объект для синхронизации, а не для пометки метода как синхронизированного. Это препятствует тому, чтобы что-то внешнее для вас, класс, захватило блокировку и заблокировало вещи.

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

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

1 голос
/ 10 февраля 2012

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

...