今天java群里一个网友问了一个多线程的问题,代码我简化一下如下BankCard.java
public class BankCard
{
 private int num;
 public int getNum() {
  return num;
 }
 public void setNum(int num) {
  this.num = num;
 }
}
Father.java
public class Father implements Runnable {
 private BankCard bc;
 private int temp;
 public Father(BankCard bc) {
  this.bc = bc;
 }
 public void run() {
temp = bc.getNum();
  while (true) {
   synchronized (bc) {
    if (temp <= 5000) {
     temp = bc.getNum();
     System.out.println(temp + "...........");
     temp += 1500;
     bc.setNum(temp);
     System.out.println("父親放進了1500,现在剩余+" + temp);
    } else
     Thread.yield();
   }
  }
 }
}
GrandFather.java
public class GrandFather implements Runnable {
 private int temp ;
 private BankCard bc;
 
 public GrandFather(BankCard bc)
 {
  this.bc = bc;
 }
 public void run() {
  temp = bc.getNum();
  while(true)
  {
  synchronized (bc) {
   if (temp <= 5000) {
    temp = bc.getNum();
    temp += 800;
    bc.setNum(temp);
    System.out.println("爺爺放進了800钱,现在剩余+"+temp);
   }
   else
    Thread.yield();
  }
 }
 }
}
Mother.java
public class Mother implements Runnable {
 private int temp;
 private BankCard bc;
 
 public Mother(BankCard bc)
 {
  this.bc = bc;
 }
 public void run() {
temp = bc.getNum();
  while (true) {
   synchronized (bc) {
    
    if (temp <= 5000) {
     temp = bc.getNum();
     temp += 1200;
     bc.setNum(temp);
     System.out.println("母親存近了1200,现在剩余+"+temp);
    }
    else
     Thread.yield();
    
   }
  }
 }
}
Test.java
public class Test
{
 public static void main(String args[])
 {
  BankCard bc = new BankCard();
  Father ft = new Father(bc);
  Mother mt = new Mother(bc);
  GrandFather gft = new GrandFather(bc);
  Thread thread = new Thread(ft);
  thread.start();
  Thread thread1 = new Thread(mt);
  thread1.start();
  Thread thread2= new Thread(gft);
  thread2.start();  
 }
}
那么这个程序的意思就是父亲,母亲,祖父,都可以向银行卡里存钱,如果超过了5000就不能再存
那么我们看结果

问题出现了,父亲最后存完钱钱已经超出5000了,为6000元,为什么爷爷和母亲都还能存呢?
为了解决这个问题,我们在run方法下的第一个temp = bc.getNum();语句前后分别加上
System.out.println("看看祖父怎么回事");
temp = bc.getNum();
System.out.println("看看祖父怎么回事"+temp);三个文件分别换成对应名字
再看结果,因为多线程每次运行结果不同,我们以接下来的结果说明

程序刚开始执行,三个线程执行run方法,然后系统将执行权交给父亲线程
然后父亲执行三次循环,系统将执行权交给祖父线程,祖父线程执行到System.out.println("看看祖父怎么回事"+temp);这一句时将执行权交给母亲线程,母亲线程同样执行一次循环,存入1200,现在卡上有5700,按道理来讲剩下的人不能再存了,但如图所示,爷爷和父亲又都各自存了一次,为什么呢?
因为在父亲交换执行权的时候父亲线程的temp值已经变为4500
然后祖父交换执行权的时候祖父线程的temp值同样为4500
而母亲执行完后仅仅是母亲线程的temp变为4500,而另外两个线程的temp值还都为4500
所以他们2个各自都还能再循环一次,故出现了这种情况
那么解决办法就是将run方法下的第一个temp = bc.getNum();语句放进synchronized 之中,if循环体之外,保证当前线程获得同步监视器锁定时再重新读取金钱数目,或者if(temp <= 5000)条件变为bc.getNum()<=5000,就避免了这种看似同步实际不同步的问题