版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/qq_25246305/article/details/82562325
线程安全问题的产生简单来说有两点,一是存在共享数据,二是存在多个线程同时操作共享数据。要解决这个问题,我们会想把处理共享数据的操作原子化,当一个线程在处理共享数据时,不允许其他线程同时处理它。换句话说,我们要把处理共享数据的这段逻辑“锁住”。
去银行
场景:俩人去银行,一个人存50块钱,另一个人取80块钱。银行一开始有一百块钱。
public class Bank {
private static int total = 100;
static class Service implements Runnable{
private int money;
private int operate;
public Service(int money, int operate) {
this.money = money;
this.operate = operate;
}
@Override
public void run() {
total = operate == 0 ? total + money : total - money;
System.out.println((operate == 0 ? "存入" : "取出") + money + "元,余额" + total + "元");
}
}
public static void main(String[] args) {
Service moneyIn = new Service(50, 0);
Service moneyOut = new Service(80, 1);
Thread inThread = new Thread(moneyIn);
Thread outThread = new Thread(moneyOut);
inThread.start();
outThread.start();
}
}
输出:
存入50元,余额70元
取出80元,余额70元
这个时候第一个人就懵逼了:我存的五十块钱哪去了?咋还倒少了三十???
实际上是在“存入50修改余额”到“打印存入50元,余额70元”这两个操作中间,第二个人已经完成了取钱的操作,余额已经变成了100+50-80=70。为了不让第一个人懵逼,我们应该把存钱取钱和打印余额的操作原子化,把这段逻辑锁住。
public class Bank {
private static int total = 100;
static class Service implements Runnable{
private int money;
private int operate;
public Service(int money, int operate) {
this.money = money;
this.operate = operate;
}
@Override
public synchronized void run() {
total = operate == 0 ? total + money : total - money;
System.out.println((operate == 0 ? "存入" : "取出") + money + "元,余额" + total + "元");
}
}
public static void main(String[] args) {
Service moneyIn = new Service(50, 0);
Service moneyOut = new Service(80, 1);
Thread inThread = new Thread(moneyIn);
Thread outThread = new Thread(moneyOut);
inThread.start();
outThread.start();
}
}
输出:
存入50元,余额150元
取出80元,余额70元
用synchronized把run方法锁住,同一时刻只有一个线程能进去操作total这个共享变量。