今天java群里一个网友问了一个多线程的问题,代码我简化一下如下BankCard.java
public class BankCard
{
private int num;
{
private int num;
public int getNum() {
return num;
}
return num;
}
public void setNum(int num) {
this.num = num;
}
}
this.num = num;
}
}
Father.java
public class Father implements Runnable {
private BankCard bc;
private int temp;
private int temp;
public Father(BankCard bc) {
this.bc = 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();
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
}
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();
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();
}
}
temp = bc.getNum();
temp += 800;
bc.setNum(temp);
System.out.println("爺爺放進了800钱,现在剩余+"+temp);
}
else
Thread.yield();
}
}
}
}
Mother.java
Mother.java
public class Mother implements Runnable {
private int temp;
private BankCard bc;
public Mother(BankCard bc)
{
this.bc = bc;
}
public Mother(BankCard bc)
{
this.bc = bc;
}
public void run() {
temp = bc.getNum();
while (true) {
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();
}
}
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就不能再存
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();
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,就避免了这种看似同步实际不同步的问题
转载于:https://blog.51cto.com/lovejjhao/411734