2 u013614197 u013614197 于 2016.03.04 19:52 提问

求助个Java多线程的demo问题

public class ThreadDemo {

public static void main(String[] args) {
    new ThreadDemo().run();
}

public void run() {
    Family f = new Family();
    new Thread(f, "qizi").start();
    new Thread(f, "zhangfu").start();
    while (true) {
        if (f.getTimes() >= 2) {
            f.show();
            break;
        }
    }

}



class Family implements Runnable {
    private int saveMoney;
    private int getMoney;
    private int curMoney;// 当前取的钱
    private int times = 0;

    // 可以直接创建一个对象来作为同步锁的钥匙
    Object key = new Object();

    public Family() {
        saveMoney = 10000;
        getMoney = 2000;
        curMoney = 0;
    }

    public int getTimes() {
        return times;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        getMoney();
    }

    // 同步方法,默认使用this作为钥匙
    public synchronized void getMoney() {
        System.out.println(Thread.currentThread().getName() + "qule" + getMoney);
        curMoney += getMoney;
        int temp = saveMoney - getMoney;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        saveMoney = temp;
        times++;
        //System.out.println(times);
    }

    public void show() {
        System.out.println("yinhanghaiyou" + saveMoney + "jialihaiyou" + curMoney);
    }

}

}


正常运行的时候会卡死在while循环那里,Debug模式下正常,如果在while循环内添加一条输出语句,程序也是正常的,求解是什么问题

3个回答

broust
broust   2016.03.07 14:09
已采纳

public int getTimes() {
return times;
}
//times非volatile的,因此主线程调用该方法的时候,并不会要求刷新缓存,所以执行到 if (f.getTimes() >= 2) 的时候,条件一直不满足。
你将times的定义加上volatile看下就对了。
至于为何debug或则加上sysout后就正确,我估计是因为由于加长了主线程的执行时间,导致主线程的缓存被刷新了。

u013614197
u013614197 嗯嗯,已经找到问题了,是可见性的问题,一直忘了这边也发了提问,感谢
2 年多之前 回复
luochoudan
luochoudan   Ds   Rxr 2016.03.04 22:39

这可奇了,运行了好几遍,只有一种输出:
qiziqule2000
zhangfuqule2000
yinhanghaiyou6000jialihaiyou4000
不知卤煮问题如何来的?

wojiushiwo945you
wojiushiwo945you   Ds   Rxr 2016.03.05 12:27

分析了下,你的代码没有问题,锁同步代码也是正确的,需要改进的是你的getTimes方法操作了共享成员变量times,也需要同步处理,但是不影响执行结果。
我的开发环境是jdk1.8+Eclipse4.5,运行N>10次,结果为:

qiziqule2000
zhangfuqule2000
yinhanghaiyou6000jialihaiyou4000
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
Java多线程之生产者消费者demo
Java多线程之生产者消费者demo
java多线程同步:生产者与消费者问题
消费者与生产者问题是线程同步里边一个很经典的问题。 用通俗的语言来描述:一群生产者不断的生产产品,并将产品放到一个容器里边;同时一群消费者不断从容器里边消费产品。 容器的容量是有限的。如果容器满了,生产者不能再往容器放产品,必须进入等待状态。等待产品被消费者拿走了,再往容器放产品。 同样,如果容器空了,消费者也必须进入等待状态。等待生产者往里边放产品,再将消费者唤醒。 下边我们来看看如何用
多线程并发demo
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore;public class ThreadTest { private static int thread_num = 500; private
java多线程简单demo
1.没有加上同步机制 import java.util.ArrayList; import java.util.List; import com.yingze.thread.ThreadDemo1.CarBigHouse.Car; /** * @ClassName: ThreadDemo1 * @Description: TODO(没有加上同步机制) * @author liang
JAVA多线程并发Demo
一个最简单的多线程并发demo:主函数:public class multithreadReq { private static final int THREADNUM = 5;//线程数量 public static void main(String[] args) { //线程数量 int threadmax = THREADNUM;
40个java多线程问题总结
http://blog.csdn.net/kimylrong/article/details/17716175
Java多线程售票问题
1、代码 public class Test { public static void main(String[] args) { Tickets tickets = new Tickets(10); new Thread(tickets, "售票员A").start(); new Thread(tickets, "售票员B").start(); new Thread(
java多线程(100个线程向同一个账户充值1元)
java实现多线程的两种方式 1、继承Thread类 ,public  class TestThread extend Thread{} 2实现Runnable接口,public class TestThred implements  Runnable{} 没有同步的情况下,代码如下 //账户类 public class Account {  private double bala
JAVA多线程demo
<br />在 Java 程序中使用多线程要比在 C 或 C++ 中容易得多,这是因为 Java 编程语言提供了语言级的支持。本文通过简单的编程示例来说明 Java 程序中的多线程是多么直观。读完本文以后,用户应该能够编写简单的多线程程序。 <br />为什么会排队等待?<br />下面的这个简单的 Java 程序完成四项不相关的任务。这样的程序有单个控制线程,控制在这四个任务之间线性地移动。此外,因为所需的资源 ? 打印机、磁盘、数据库和显示屏 -- 由于硬件和软件的限制都有内在的潜伏时间,所以每项任务都
Java 多线程同步与死锁
在多线程中如何找到安全问题所在: 1,明确哪些代码是多线程运行代码 2,明确共享数据 3,明确多线程运行代码中哪些代码是操作共享数据的 静态的同步方法中,使用锁是该方法所在类的字节码文件对象,即 类名.class  前天俺们谈到了加锁,但是在使用加锁的同时又会带来一个问题,就是死锁。什么叫死锁? 所谓死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而