作用:把出现线程安全问题的核心代码给上锁。
原理:每次只能一个线程进入,执行完毕后自动解锁,其他线程才可以进来执行。
synchronized(同步锁对象){
操作资源共享的代码(核心代码)
}
锁对象的要求:
理论上:锁对象只要对于当前同时执行的线程来说是同一个对象即可。
锁对象用任意唯一的对象好不好呢?
不好,会影响其他无关线程的执行。
锁对象的规范要求:
规范上:建议使用共享资源作为锁对象。
对于实例方法建议使用this作为锁对象。
对于静态方法建议使用字节码(类名.class)对象作为锁对象。
是同步代码块好还是同步方法好一点?
同步代码快锁的范围更小,同步方法锁的范围更大
下面来看案例演示:
public class ThreadDemo5 {
//模拟取钱案例
//两个线程
public static void main(String[] args) {
Accout acc=new Accout("ICBC-111",100000);
new DrawThread(acc,"小明").start();
new DrawThread(acc,"小红").start();
}
}
//新建一个类模拟取钱
public class DrawThread extends Thread {
private Accout acc;
public DrawThread(Accout acc, String name) {
super(name);
this.acc = acc;
}
@Override
public void run() {
//取钱的
acc.drawMoney(100000);
}
}
//属性和方法
public class Accout{
private String cardId;
private double money;
public String getCardId() {
return cardId;
}
public void setCardId(String cardId) {
this.cardId = cardId;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public Accout(String cardId, double money) {
this.cardId = cardId;
this.money = money;
}
public Accout() {
}
public String toString() {
return "Accout{cardId = " + cardId + ", money = " + money + "}";
}
//同步方法
//同步方法锁底层原理
/*
同步方法其实底层也是有隐式锁对象的,只是锁的范围是整个方法代码
如果方法是实例方法:同步方法默认用this作为的锁对象。但代码要高度面向对象
如果方法是静态方法:同步方法默认用类名.class作为的锁对象
*/
public synchronized void drawMoney(double money) {
//先获取是谁来取钱,现成的名字就是人名
String name =Thread.currentThread().getName();
//判断账户是否够钱
//synchronized 同步代码块
//synchronized ("beiyou") {
if (this.money >= money) {
//取钱
System.out.println(name + "来取钱成功,吐出"+money);
//更新余额
this.money -= money;
System.out.println(name + "取钱后剩余:"+this.money);
}else {
System.out.println(name + "来取钱,余额不足!");
}
//}
}
}