package com.test;public class ThreadTest{
public static void main(String[] args) {
Bank bank = new Bank();
Thread th1 = new MyThread(bank);
Thread th2 = new MyThread(bank);
th1.start();
th2.start();
}
}class Bank{
private int money = 1000;
public Object getMoney (int getMoney){
synchronized (this){
while(getMoney < 0 || getMoney > money){
return "ERROR!";
}
money -= getMoney;
return getMoney;
}
}
}class MyThread extends Thread{
Bank bank;
MyThread(Bank bank){
this.bank = bank;
}
@Override
public void run() {
System.out.println(bank.getMoney(800));
}
}这是代码 建立两个线程,调用synchronized方法,却是并发 结果输出ERROR! 800 顺序不定,求问这是为何?
public static void main(String[] args) {
Bank bank = new Bank();
Thread th1 = new MyThread(bank);
Thread th2 = new MyThread(bank);
th1.start();
th2.start();
}
}class Bank{
private int money = 1000;
public Object getMoney (int getMoney){
synchronized (this){
while(getMoney < 0 || getMoney > money){
return "ERROR!";
}
money -= getMoney;
return getMoney;
}
}
}class MyThread extends Thread{
Bank bank;
MyThread(Bank bank){
this.bank = bank;
}
@Override
public void run() {
System.out.println(bank.getMoney(800));
}
}这是代码 建立两个线程,调用synchronized方法,却是并发 结果输出ERROR! 800 顺序不定,求问这是为何?
th1.start();
th2.start();
是启动了两个线程,运行了2个run,两个run同时调用System.out.println(bank.getMoney(800))你只能保证同步块中肯定是getMoney先为800,然后返回了800,此时已经出了同步块,有可能还没轮到System.out.println(bank.getMoney(800))执行,而轮到另一个bank.getMoney(800)执行,此时会返回error,由于两次的System.out.println(bank.getMoney(800))跟锁没有关系,所以不能保证这两个语句谁先执行,所以不能确定先打印哪个。
如果你在
synchronized (this){
while(getMoney < 0 || getMoney > money){
return "ERROR!";
}
System.out.println("[" + getMoney + "]");
money -= getMoney;
return getMoney;
}插入一个输出,那么肯定是先输出800。这个问题的原因其实就是同步块控制的范围小了,超出同步块的范围就控制不了顺序了。
当你th1.start()后
money -= getMoney;
money变成 1000-800 =200了
因为下面代码
synchronized (this){
while(getMoney < 0 || getMoney > money){
return "ERROR!";
}
是线程安全的,所以当下一个线程执行这段代码的时候,money==200 getMoney > money 是true
进入while循环,返回"ERROR!" 至于800是前面一个线程返回的
为什么顺序不定,这个就要看调度了
synchronized (this){
Thread.sleep(1000);
while(getMoney < 0 || getMoney > money){
return "ERROR!";
}休眠一下,然后你再看看效果吧。