引入一个 场景:
*一家包子店每天限量销售包子
* 现在包子店还剩5个包子
* 张三和李四同时在不同窗口买包子,张三要买3个,李四也要买3个
Buy类用于展示购买结果
class Buy {
public static int left = 5;
/*
* @name 购买者姓名
* @num 购买包子数量
*/
public void buy_bread(String name, int num) {
left = left - num;
if (left < 0) {
System.out.println(name + ",There's no engous bread left!");
return;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
System.out.println(name + " has bought " + num + " bread, there's " + left + " bread left");
}
}
Store类模拟场景中的故事
public class Store implements Runnable {
static Buy buy = new Buy();
public static void main(String[] args) {
Store w = new Store();
Thread t1 = new Thread(w) {
@Override
public void run() {
// 打东边来了个张三,他要买3个包子
buy.buy_bread(Thread.currentThread().getName(),3 );
}
};
Thread t2 = new Thread(w) {
@Override
public void run() {
// 打西边来了个李四,也要买3个包子
buy.buy_bread(Thread.currentThread().getName(), 3);
}
};
t1.setName("zhangsan");
t2.setName("lisi");
t1.start();
t2.start();
}
@Override
public void run() {
// TODO Auto-generated method stub
}
}
运行结果
lisi,There's no engous bread left!
zhangsan has bought 3 bread, there's -1 bread left
按道理来讲,因为只有5个包子,两个人同时来买,每个人都买3个,必然是有一个人能够买到,另一个人买不到,最终还剩2个包子。但是结果为什么是李四一来就没有包子了,张三买了3个最终包子为负数了?
原因是张三先来买包子,它买了包子还没来得及输出购买结果的时候(此时left已经等于2),线程睡着了,所以方法执行被打断了(Buy类中的Thread.sleep(1);)。即使不睡着也可能被打断,只是为了更好的模拟。这时候李四来了,先判断left-3,发现小于0,告诉李四包子不够了,直接return,李四的线程就结束了。又切换到张三的线程,输出left,因为left刚刚被李四修改过了,所以是-1。
那么,有什么办法让张三买包子直到输出完状态,其他人不得在中途抢占资源呢?这就引入了synchronized,synchronized可以锁定当前代码段,保证现有资源不被抢占,直到执行完锁定的片段。
class Buy {
public static int left = 5;
/*
* @name 购买者姓名
* @num 购买包子数量
*/
public void buy_bread(String name, int num) {
synchronized (this) {
left = left - num;
if (left < 0) {
System.out.println(name + ",There's no engous bread left!");
return;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
System.out.println(name + " has bought " + num + " bread, there's " + left + " bread left");
}
}
}
结果输出:
lisi has bought 3 bread, there's 2 bread left
zhangsan,There's no engous bread left!
现在终于能正常买包子了!