# 使用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.balance和this.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同理.