synchronized block - lock more than one object

前端 未结 5 979
情书的邮戳
情书的邮戳 2021-01-31 02:26

I\'m modelling a game where multiple players (threads) move at the same time. The information of where a player is located at the moment is stored twice: the player has a variab

5条回答
  •  Happy的楠姐
    2021-01-31 02:55

    In fact, synchronization is for code, not objects or data. The object reference used as a parameter in synchronized block represent the lock.

    So if you have code like:

    class Player {
    
      // Same instance shared for all players... Don't show how we get it now.
      // Use one dimensional board to simplify, doesn't matter here.
      private List[] fields = Board.getBoard(); 
    
      // Current position
      private int x; 
    
      public synchronized int getX() {
        return x;
      }
    
      public void setX(int x) {
        synchronized(this) { // Same as synchronized method
          fields[x].remove(this);
          this.x = x;
          field[y].add(this);
        }
      }
    }
    

    Then Despite being in the synchronized block the access to field is not protected because the lock is not the same (it being on different instances). So your List of Players for your board can become inconsistent and cause runtime exceptions.

    Instead if you write the following code, it will work because we have only one shared lock for all players:

    class Player {
    
      // Same instance shared for all players... Don't show how we get it now.
      // Use one dimensional board to simplify, doesn't matter here.
      private List[] fields; 
    
      // Current position
      private int x;
    
      private static Object sharedLock = new Object(); // Any object's instance can be used as a lock.
    
      public int getX() {
        synchronized(sharedLock) {
          return x;
        }
      }
    
      public void setX(int x) {
        synchronized(sharedLock) {
          // Because of using a single shared lock,
          // several players can't access fields at the same time
          // and so can't create inconsistencies on fields.
          fields[x].remove(this); 
          this.x = x;
          field[y].add(this);
        }
      }
    }
    

    Be sure to use only a single lock to access all the players or your board's state will be inconsistent.

提交回复
热议问题