Welcome 微信登录

首页 / 软件开发 / JAVA / Java线程机制(四) 同步方法和同步块

Java线程机制(四) 同步方法和同步块2013-12-07 cnblogs 文酱在之前例子的基础上,我们增加新的功能:根据正确与不正确的响应来显示玩家的分数。

public class ScoreLabel extends JLabel implements CharacterListener {private volatile int score = 0;private int char2type = -1;private CharacterSource generator = null, typist = null;public ScoreLabel(CharacterSource generator, CharacterSource typist) {this.generator = generator;this.typist = typist;if (generator != null) {generator.addCharacterListener(this);}if (typist != null) {typist.addCharacterListener(this);}}public ScoreLabel() {this(null, null);}public synchronized void resetGenerator(CharacterSource newCharactor) {if (generator != null) {generator.removeCharacterListener(this);}generator = newCharactor;if (generator != null) {generator.addCharacterListener(this);}}public synchronized void resetTypist(CharacterSource newTypist) {if (typist != null) {typist.removeCharacterListener(this);typist = newTypist;}if (typist != null) {typist.addCharacterListener(this);}}public synchronized void resetScore() {score = 0;char2type = -1;setScore();}private synchronized void setScore() {SwingUtilities.invokeLater(new Runnable() {@Overridepublic void run() {setText(Integer.toString(score));}});}@Overridepublic synchronized void newCharacter(CharacterEvent ce) {if (ce.source == generator) {if (char2type != -1) {score--;setScore();}char2type = ce.character;} else {if (char2type != ce.character) {score--;} else {score++;char2type = -1;}setScore();}}}
这里我们将newCharacter()方法用synchronized进行同步,是因为这个方法会被多个线程调用, 而我们根本就不知道哪个线程会在什么时候调用这个方法。这就是race condition。
    变量的volatile无法解决上面的多线程调度问题,因为这里的问题是方法调度的问题,而且更加可怕的是,需 要共享的变量不少,其中有些变量是作为条件判断,这就会导致在这些条件变量没有正确的设置前,有些线程 已经开始启动了。

这并不是简单的将这些变量设置为volatile就能解决的问题,因为就算这些变量的 状态不对,其他线程依然能够启动。

这里有几个方法的同步是需要引起我们注意的:resetScore (),resetGenerator()和resetTypist()这几个方法是在重新启动时才会被调用,似乎我们不需要为此同步它们 :其他线程这时根本就没有开始启动!!

但是我们还是需要同步这些方法,这是一种防卫性的设计, 保证整个Class所有相关的方法都是线程安全的。遗憾的是,我们必须这样考虑,因为多线程编程的最大问题 就是我们永远也不知道我们的程序会出现什么问题,所以,任何可能会引起线程不安全的因素我们都要尽量避 免。

这也就引出我们的问题:如何能够对两个不同的方法同步化以防止多个线程在调用这些方法的时 候影响对方呢?

对方法做同步化,能够控制方法执行的顺序,因为某个线程上已经运行的方法无法被 其他线程调用。这个机制的实现是由指定对象本身的lock来完成的,因为方法需要访问的对象的lock被一个线 程占有,但值得注意的是,所谓的对象锁其实并不是绑定在对象上,而是对象实例上,如果两个线程拥有对象 的两个实例,它们都可以同时访问该对象,