模拟场景:
写一段小程序,一个方法给某人账户充值,另一个方法查询某人的账户,如果两个方法都不加锁,并发情况下肯定会问题,现在只给充值方法加锁,查询方法不加,由于synchronized与非synchronized方法可以同时运行,所以查询方法可能产生脏读问题。
public class Account {
String name;
double balance;
public synchronized void setBalance(String name, double balance) {
this.name = name;
try {
Thread.sleep(2000);
} catch (InterruptedException exception) {
exception.printStackTrace();
}
this.balance = balance;
}
public double getBalance(String name) {
if (name.equals(this.name)) {
return this.balance;
}
return 0.0;
}
public static void main(String[] args) throws InterruptedException {
Account acc = new Account();
new Thread(() -> acc.setBalance("张三", 100)).start();
TimeUnit.SECONDS.sleep(1);//暂停1秒
/**
* setBalance还未执行完成,读到的还是balance的默认值,即0.0,也就是脏读
*/
System.out.println(acc.getBalance("张三"));
TimeUnit.SECONDS.sleep(2);//再暂停3秒
/**
* setBalance已执行完成,读到的是balance的最新值,即100.0
*/
System.out.println(acc.getBalance("张三"));
}
}
结果
0.0
100.0
是否需要给读方法同时加上synchronized?看需求,如果需求场景允许出现脏读(仅仅是读,不进行任何写操作),可以不用加,加上synchronized性能将急剧下降,如果场景不允许脏读,该加还是要加。
另
public synchronized double getBalance(String name) {
if (name.equals(this.name)) {
return this.balance;
}
return 0.0;
}
public double getBalance(String name) {
synchronized (this) {
if (name.equals(this.name)) {
return this.balance;
}
return 0.0;
}
}
public static synchronized void fun(){
// to do something
}
//等价于
public static void fun(){
synchronized(Account.class){
// to do something
}
}