如何改善Java中锁的性能(1)(2)
分享于 点击 37022 次 点评:39
缩小锁的作用范围
现在,当确信了需要保护的是数据而非程序后,我们应该确保我们只在必要的地方加锁——例如当上面的代码被重构之后:
- public class GameServer {
- public Map> tables = new HashMap>();
- public void join(Player player, Table table) {
- if (player.getAccountBalance() > table.getLimit()) {
- synchronized (tables) {
- List tablePlayers = tables.get(table.getId());
- if (tablePlayers.size() < 9) {
- tablePlayers.add(player);
- }
- }
- }
- }
- //other methods skipped for brevity
- }
这样那段包含对玩家账号余额检测(可能引发IO操作)的可能引起费时操作的代码,被移到了锁控制的范围之外。注意,现在锁仅仅被用来防止玩家人数超过桌子可容纳的人数,对账户余额的检查不再是该保护措施的一部分了。
分离锁
你可以从上面例子最后一行代码清楚的看到:整个数据结构是由相同的锁保护着。考虑到在这一种数据结构中可能会有数以千计的牌桌,而我们必须保护任何一张牌桌的人数不超过容量,在这样的情况下仍然会有很高的风险出现竞争事件。
关于这个有一个简单的办法,就是对每一张牌桌引入分离锁,如下面这个例子所示:
- public class GameServer {
- public Map> tables = new HashMap>();
- public void join(Player player, Table table) {
- if (player.getAccountBalance() > table.getLimit()) {
- List tablePlayers = tables.get(table.getId());
- synchronized (tablePlayers) {
- if (tablePlayers.size() < 9) {
- tablePlayers.add(player);
- }
- }
- }
- }
- //other methods skipped for brevity
- }
现在,我们只对单一牌桌的可访问性进行同步而不是所有的牌桌,这样就显著降低了出现锁竞争的可能性。举一个具体的例子,现在在我们的数据结构中有100个牌桌的实例,那么现在发生竞争的可能性就会比之前小100倍。

用户点评