Java多线程编程实例(2)

把锁作为一个私有的对象,外部不能拿到这个对象,更安全一些。对象可能被其他线程直接进行加锁操作,此时线程便持有了该对象的对象锁,例如下面这种情况:

class A {
    public void method1() {
    }
}

class B {
    public void method1() {
        A a = new A();
        synchronized (a) { //直接进行加锁
      a.method1();

}
    }
}

这种使用方式下,对象a的对象锁被外部所持有,让这把锁在外部多个地方被使用是比较危险的,对代码的逻辑流程阅读也造成困扰。一种更好的方式是在类的内部自己管理锁,外部需要同步方案时,也是通过接口方式来提供同步操作:

class A {
    private Object lock = new Object();
    public void method1() {
        synchronized (lock){
           
        }
    }
}

class B {
    public void method1() {
        A a = new A();
        a.method1();
    }
}

五、进行适当的锁分解

考虑下面这段程序:

public class GameServer {
  public Map<String, List<Player>> tables = new HashMap<String, List<Player>>();

public void join(Player player, Table table) {
    if (player.getAccountBalance() > table.getLimit()) {
      synchronized (tables) {
        List<Player> tablePlayers = tables.get(table.getId());
        if (tablePlayers.size() < 9) {
          tablePlayers.add(player);
        }
      }
    }
  }
  public void leave(Player player, Table table) {/*省略*/}
  public void createTable() {/*省略*/}
  public void destroyTable(Table table) {/*省略*/}
}

在这个例子中,join方法只使用一个同步锁,来获取tables中的List<Player>对象,然后判断玩家数量是不是小于9,如果是,就调增加一个玩家。当有成千上万个List<Player>存在tables中时,对tables锁的竞争将非常激烈。在这里,我们可以考虑进行锁的分解:快速取出数据之后,对List<Player>对象进行加锁,让其他线程可快速竞争获得tables对象锁:

public class GameServer {
  public Map<String, List<Player>> tables = new HashMap<String, List<Player>>();

public void join(Player player, Table table) {
    if (player.getAccountBalance() > table.getLimit()) {
      List<Player> tablePlayers = null;
      synchronized (tables) {
          tablePlayers = tables.get(table.getId());
      }
     
      synchronized (tablePlayers) {
        if (tablePlayers.size() < 9) {
          tablePlayers.add(player);
        }
      }
    }
  }

public void leave(Player player, Table table) {/*省略*/}
 public void createTable() {/*省略*/}
 public void destroyTable(Table table) {/*省略*/}
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/f5c75f0d7c0cdfb792c2659c27373504.html