Получите WriteLock перед записью общего ресурса - PullRequest
0 голосов
/ 07 февраля 2019

Я новичок в многопоточности и наткнулся на этот пример на ReadWriteLock.

ScoreBoard

public class ScoreBoard {
private boolean scoreUpdated = false;
private int score = 0;
    String health = "Not Available";
final ReentrantReadWriteLock rrwl = new ReentrantReadWriteLock();
public String getMatchHealth() {
    rrwl.readLock().lock();
    if (scoreUpdated) {
        rrwl.readLock().unlock();
        rrwl.writeLock().lock();
        try {
          if (scoreUpdated) {
              score = fetchScore();
              scoreUpdated = false;
          }
          rrwl.readLock().lock();
        } finally {
          rrwl.writeLock().unlock(); 
        }   
    }   
    try {
         if (score % 2 == 0 ){
              health = "Bad Score";
          } else {
              health = "Good Score";
          }
    } finally {
          rrwl.readLock().unlock();
        }
    return health;
}
public void updateScore() {
    try {
        rrwl.writeLock().lock();
        //perform more task here
        scoreUpdated = true;
    }finally {
        rrwl.writeLock().unlock();
    }
}
private int fetchScore() {
    Calendar calender = Calendar.getInstance();
    return calender.get(Calendar.MILLISECOND);
}
}

ScoreUpdateThread

public class ScoreUpdateThread implements Runnable {
private ScoreBoard scoreBoard;
public ScoreUpdateThread(ScoreBoard scoreTable) {
    this.scoreBoard = scoreTable;
}
@Override
public void run() {
    for(int i= 0; i < 5; i++) {
        System.out.println("Score Updated.");       
        scoreBoard.updateScore();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
}

Main

public class Main {
public static void main(String[] args) {
    final int threadCount = 2;
    final ExecutorService exService = Executors.newFixedThreadPool(threadCount);
    final ScoreBoard scoreBoard = new ScoreBoard();
    exService.execute(new ScoreUpdateThread(scoreBoard));
    exService.execute(new ScoreHealthThread(scoreBoard));           
    exService.shutdown();
}
}   

При ScoreBoard при обновлении переменной health нам необходимо получить WriteLock, так как мыобновить разделяемую переменную?

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Wont в ScoreBoard при обновлении переменной health, нам нужно получить WriteLock, так как мы обновляем общую переменную?

Вы правы, чтоМетод класса getMatchHealth() выполняет модификацию общей переменной health без удержания блокировки записи.Поскольку в классе нет другого механизма для синхронизации этих записей, это создает гонку данных, когда два потока вызывают getMatchHealth() в одном и том же ScoreBoard, не задействуя какую-либо форму внешней синхронизации.Это кажется недостатком метода, и у метода, похоже, есть и другие, более тонкие проблемы синхронизации.

Тем не менее, представленная программа, кажется, никогда не вызывает getMatchHealth() вообще, идругие ScoreBoard методы, по-видимому, свободны от недостатков синхронизации, поэтому недостатки представленной программы не затрагиваются.Тем не менее, если только эти недостатки не являются преднамеренными - например, для дидактических целей - я бы порекомендовал найти лучший учебный материал, чем тот, который предоставил пример программы.

0 голосов
/ 07 февраля 2019

Я не знаю точно, с какой проблемой вы сталкиваетесь, но я думаю, что проблема заключается в следующем: 1) Вы должны сделать переменные ScoreUpdated и Health открытыми и изменчивыми, в настоящее время они являются частными и по умолчанию соответственно.

2) Когда вы берете блокировку записи в методе getMatchHealth () перед ее освобождением, вы снова берете блокировку чтения, которую вы сняли незадолго до этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...