# 使用synchronized的四种方式

# 修饰类

# 修饰实例方法

# 修饰静态方法

# 同步块

# 简述synchronized的实现

其同步实现原理是在对象头中做锁标记, 对象头是在heap中.

# 分析synchronized使用场景

# 场景一, 简单常用的场景

class Account {
  // 锁:保护账户余额
  private final Object balLock
    = new Object();
  // 账户余额  
  private Integer balance;
  // 锁:保护账户密码
  private final Object pwLock
    = new Object();
  // 账户密码
  private String password;

  // 取款
  void withdraw(Integer amt) {
    synchronized(balLock) {
      if (this.balance > amt){
        this.balance -= amt;
      }
    }
  } 
  // 查看余额
  Integer getBalance() {
    synchronized(balLock) {
      return balance;
    }
  }

  // 更改密码
  void updatePassword(String pw){
    synchronized(pwLock) {
      this.password = pw;
    }
  } 
  // 查看密码
  String getPassword() {
    synchronized(pwLock) {
      return password;
    }
  }
}

# 场景二, 容易发现问题的场景, 但不容易分析原因

在场景一的基础上, 将Object锁换成this.balancethis.password, 不单独设置锁对象.

class Account {
  // 账户余额  
  private Integer balance;
  // 账户密码
  private String password;

  // 取款
  void withdraw(Integer amt) {
    synchronized(this.balance) {
      if (this.balance > amt){
        this.balance -= amt;
      }
    }
  } 
  // 查看余额
  Integer getBalance() {
    synchronized(this.balance) {
      return balance;
    }
  }

  // 更改密码
  void updatePassword(String pw){
    synchronized(this.password) {
      this.password = pw;
    }
  } 
  // 查看密码
  String getPassword() {
    synchronized(this.password) {
      return password;
    }
  }
}

场景二分析说明

balance是可变对象, 在多线程场景下, 某一线程修改balance后, 其他线程准备调用的线程由于锁对象的改变, 即想持有的锁发生了改变, 与balance改动之前便被阻塞的线程相比较, 他们想持有的锁不同, 便出现多把锁对应同一个资源, 会出现锁不住资源的情况, 进而会导致可见性问题, 从而出现资源被覆盖的可能.

balance与password同理.

修改于: 8/11/2022, 3:17:56 PM