在写入共享资源之前获取WriteLock

时间:2019-02-07 14:20:48

标签: java multithreading locking

我是多线程技术的初学者,在ReadWriteLock上遇到了这个示例。

记分板

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();
        }
    }
}
}

主要

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 :(得分:1)

  

在更新ScoreBoard变量时不会在health中输入,因为我们要更新共享变量,所以我们需要获取WriteLock吗?

您正确的是,该类的getMatchHealth()方法对共享的health变量进行了修改而没有保持写锁定。该类中没有其他用于同步这些写入的机制,当两个线程在同一个getMatchHealth()上调用ScoreBoard而不进行某种形式的外部同步时,这会导致数据争用。这似乎是该方法的缺陷,并且该方法似乎还存在其他一些更细微的同步问题。

尽管如此,所提供的程序似乎根本无法调用getMatchHealth(),而其他ScoreBoard方法似乎没有同步缺陷,因此所提供的特定程序不受这些缺陷的影响。尽管如此,除非有这些缺陷是有意为之的(例如,出于教学目的),我还是建议您找到比提供示例程序的教程材料更好的教程材料。

答案 1 :(得分:-1)

我不确定您面临的是什么问题,但是我认为的问题是: 1)您应将scoreUpdated和health变量设置为public和volatile,当前分别为private和default。

2)当在释放方法之前对getMatchHealth()方法进行写锁定时,您将再次获取之前已释放的读锁定。