给手机账户充值一般有以下步骤:
1. 先从数据库里取手机账户信息
2. 然后手机账户 + 50块
3. 最后再写回数据库.
假设现在A,B两个人几乎同时向一个手机账户(手机余额0元)里面充了50块钱话费,在代码中,是启动了a,b两个线程,假设现在a线程还没把充值好的手机余额(50元)写回数据库,b线程已经从数据库里面取手机余额(0元),a写回数据库是50元,b操作完再写回数据库也是50元,而不是我们想要的100元.为什么会出现这种情况呢?原因就是多个线程可以同时执行同一段代码,假设只有当a线程执行完以后,b线程才能执行充值代码,这样子就不会出现问题了.那怎么才能达到这样的效果呢?答案就是用synchronized加锁.
synchronized的几种用法,他可以修饰代码块,也可以修饰普通方法,还可以修饰静态代码块.我们可以这么理解,被synchronized修饰的代码相当于加了一把锁,没有钥匙就不能执行代码,那钥匙是什么呢?在synchronized代码块中,钥匙就是synchronized后括号里面的对象;在synchronized方法中,钥匙就是持有方法的那个对象;在synchronized静态方法中,钥匙就是类对象.这个钥匙放在jvm特定的位置,当线程要执行加锁的代码的时候,线程会去指定位置看看有没有钥匙,如果没有钥匙,线程就进入等待状态,如果有钥匙,线程就可以执行锁里面的代码,执行完代码以后,线程把钥匙放到原来的位置,并切唤醒其他线程来抢钥匙.
synchronized修饰代码块
public boolean recharge(String phone, int money) {
//这里的钥匙只能是对象,this表示持有这个方法的对象;普通string不是对象,要intern以后才可以用
synchronized (this){
Account account = getAccount(phone);
account.setBalance(account.getBalance() + money);
return update(account);
}
}
synchronized修饰方法
//跟上面的this一样
public synchronized boolean recharge(String phone, int money) {
Account account = getAccount(phone);
account.setBalance(account.getBalance() + money);
return update(account);
}
synchronized修饰静态方法
//这里的对象是指类对象, 是指 object.getClass()得到的对象
public synchronized static boolean recharge(String phone, int money) {
Account account = getAccount(phone);
account.setBalance(account.getBalance() + money);
return update(account);
}