public class ThreadTestNum implements Runnable  {

public static int num = 20; public static void main(String[] args) {

Thread t1=new Thread(new ThreadTestNum());
Thread t2=new Thread(new ThreadTestNum());
Thread t3=new Thread(new ThreadTestNum());
Thread t4=new Thread(new ThreadTestNum());

t1.start();
t2.start();
t3.start();
t4.start();

}

public void run(){
sale(Thread.currentThread().getName());
}

public void sale(String name){
while(num>0){
synchronized (this) {

System.out.println(name+" 运行到了num= "+num);
num--;

}
}
}
}
为什么在切换线程的时候会出现相等的错误?????谢谢大虾了!!!!!

解决方案 »

  1.   

    synchronized (this) {System.out.println(name+" 运行到了num= "+num);
    num--;
       try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    试试
      

  2.   

    不知道这样行不/*
     * file: Pause.java
     * class: Pause
     *
     * description: 
     *
     * @author:  leisore
     * @version: V1.0.0
     */
    package cn.leisore.daily._2010_06_24;public class ClassLockDemo implements Runnable {    public static int num = 20;    public static void main(String[] args) {        Thread t1 = new Thread(new ClassLockDemo());
            Thread t2 = new Thread(new ClassLockDemo());
            Thread t3 = new Thread(new ClassLockDemo());
            Thread t4 = new Thread(new ClassLockDemo());        t1.start();
            t2.start();
            t3.start();
            t4.start();    }    public void run() {
            sale(Thread.currentThread().getName());
        }    public void sale(String name) {
            synchronized (ClassLockDemo.class) {
                while (num > 0) {
                    System.out.println(name + " 运行到了num= " + num);
                    num--;
                    try {
                        ClassLockDemo.class.wait(100);
                        ClassLockDemo.class.notifyAll();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
      

  3.   


    public void sale(String name){
    synchronized (ThreadTestNum.class) {
      while(num>0){
        System.out.println(name+" 运行到了num= "+num);
        num--;
      }
    }
    }
      

  4.   


    public void sale(String name){
     while(num>0){
         synchronized (ThreadTestNum.class) {
            try{
                Thread.sleep(1);
            }catch(Exception e){}
            if(num>0){
                System.out.println(name+" 运行到了num= "+num);
                num--;
            }
        }
     }
    //这样更符合逻辑!多跑几次才明显
      

  5.   


    将num放入同步代码块中,更加安全
      

  6.   

    谢谢各位大虾  真的很厉害  还有就是一个地方不明白 为什么synchronized()内的参数一定要是——.class 呢  我们老师教的是锁住括号内的代码要用this 还有this不是指向自身的引用对象吗  谢谢嘻嘻
      

  7.   

    为什么一定要在synchronized 内sleep或wait呢 不能直接那样同步吗
      

  8.   

    楼主的问题很简单,请看代码~
    package a;public class ThreadTestNum implements Runnable {public static int num = 20;public static void main(String[] args) {Thread t1=new Thread(new ThreadTestNum());
    Thread t2=new Thread(new ThreadTestNum());
    Thread t3=new Thread(new ThreadTestNum());
    Thread t4=new Thread(new ThreadTestNum());t1.start();
    t2.start();
    t3.start();
    t4.start();}
    public void method(){
    this.num--;
    }public void run(){
    sale(Thread.currentThread().getName());
    }public void sale(String name){
    while(num>0){
    synchronized (this) {
    this.method();
    System.out.println(name+" 运行到了num= "+num);
    }
    }
    }
    }
      

  9.   

    结果如下:Thread-0 运行到了num= 19
    Thread-1 运行到了num= 18
    Thread-2 运行到了num= 17
    Thread-3 运行到了num= 16
    Thread-1 运行到了num= 15
    Thread-2 运行到了num= 14
    Thread-3 运行到了num= 13
    Thread-1 运行到了num= 12
    Thread-2 运行到了num= 11
    Thread-3 运行到了num= 10
    Thread-0 运行到了num= 9
    Thread-2 运行到了num= 8
    Thread-3 运行到了num= 7
    Thread-0 运行到了num= 5
    Thread-1 运行到了num= 5
    Thread-2 运行到了num= 4
    Thread-3 运行到了num= 3
    Thread-0 运行到了num= 2
    Thread-1 运行到了num= 1
    Thread-2 运行到了num= 0
    说一下楼主错误的原因:sychonize(this)意思是指锁住当前的引用的对象没错,但是你实例化了另外四个Thread对象,对他们你是没有上锁的,所以他们如果都start()以后,是并行运行的,num的值在输出时就会出现问题,所以要想num的值稳定向下减少,这几个进程就要排队获得对(this)当前引用对象的操作,这样你对(this)加上synchronized才会有效果,就是说这几个启动对像每一次只能有一个进程获得(this)对象,其它都得等待,所以才会出现正确结果。呵呵,过去我也经常出现这种错误,不知楼主明白了没?
      

  10.   

    楼上几位大侠好像把问题复杂化了吧,用不到sleep()和wait()的吧~
      

  11.   

    没错。你的num没有同步。
    当然会报错。
      

  12.   

    对this同步好像不对吧
    在我机器上的结果:Thread-0 运行到了num= 18
    Thread-0 运行到了num= 17
    Thread-0 运行到了num= 16
    Thread-0 运行到了num= 15
    Thread-0 运行到了num= 14
    Thread-0 运行到了num= 13
    Thread-0 运行到了num= 12
    Thread-0 运行到了num= 11
    Thread-0 运行到了num= 10
    Thread-1 运行到了num= 18
    Thread-1 运行到了num= 8
    Thread-1 运行到了num= 7
    Thread-0 运行到了num= 9
    Thread-1 运行到了num= 6
    Thread-1 运行到了num= 4
    Thread-0 运行到了num= 5
    Thread-3 运行到了num= 1
    Thread-1 运行到了num= 2
    Thread-2 运行到了num= 3
    Thread-0 运行到了num= 018出现了两次
    说明不是现线程安全的哦
      

  13.   

    Thread t1=new Thread(new ThreadTestNum());
    Thread t2=new Thread(new ThreadTestNum());
    Thread t3=new Thread(new ThreadTestNum());
    Thread t4=new Thread(new ThreadTestNum());
    总共4个ThreadTestNum对象实例,synchronized (this)是在四个完全独立的对象上加锁,彼此没有任何关系,根本无法同步!不知道就别瞎说。
      

  14.   


    java多线程要求synchronized包起来的必须是Runnable的对象,明白了吧。你的this是什么?是Thread的一个子类,自然就是Runnable的子类。
      

  15.   


    在这里是可以同步的,因为有一个static的类变量
      

  16.   

    好吧,咱来分析分析。
    while(num>0){
       synchronized (this) {
           this.method();//其实就是this.num--;
           System.out.println(name+" 运行到了num= "+num);
        }
    }
    假如现num=1,线程1执行到while(num>0),判断结果是true,切换到线程2,此时线程2判断肯定也是true。然后,锁住线程2的ThreadTestNum这个对象,this.num--;num变为0,这时候切换到线程1,同样可以进入this.method();因为这是获得另外一个ThreadTestNum对象的锁,同样this.num--;num就变为-1了。运行暂时没错,不代表永远没错。多跑几次就知道了
      

  17.   

    wait notify一下就可知道,这个锁无效
    18楼是对的public class ThreadTestNum implements Runnable {
    public static int num = 20; public static void main(String[] args) {

    ThreadTestNum test = new ThreadTestNum();
    Thread t1=new Thread(test);
    Thread t2=new Thread(test);
    Thread t3=new Thread(test);
    Thread t4=new Thread(test); t1.start();
    t2.start();
    t3.start();
    t4.start(); }
    public void run(){
    sale(Thread.currentThread().getName());
    } public void sale(String name){
    synchronized (this){
    while(this.num>0){
    this.num--;
    System.out.println(name+" it's num= "+num);
    try {
    this.notifyAll();
    this.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }

    }
    }
    }
    }
    你这里如果要实现多个线程共享工作,就要wait notify,否则对象就一直被同一个下称锁着
      

  18.   

    不好意思,wait前要判断num是否大于0,否则最后线程不会结束
      

  19.   

    前面因为看楼主代码不慎,所以写的程序有问题,但是我也不是像楼上说的那样瞎说的,伤~~所以重新写了代码,这次应该不会再有问题了,不用wait()和notify()是绝对可以的,只需对共享资源加上一个锁,那么其他线程当然会排队等待CPU执行时间片。这一次楼主可以测试N次去检验其正确性~package a;public class Count {
    int num = 200; public void count_num() {
    this.num--;
    } public static void main(String args[]) {
    Count c = new Count();
    ThreadNum t1 = new ThreadNum(c);
    ThreadNum t2 = new ThreadNum(c);
    ThreadNum t3 = new ThreadNum(c);
    ThreadNum t4 = new ThreadNum(c);
    t1.start();
    t2.start();
    t3.start();
    t4.start();
    }
    }class ThreadNum extends Thread {
    Count t_;
    String name; public ThreadNum(Count t) {
    this.t_ = t;
    } public void run() {
    while (true) {
    synchronized (t_) {
    this.name = Thread.currentThread().getName();
    /*try {
    Thread.sleep(500);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }*/
    if(t_.num > 0){
    t_.count_num();

    }else{
    break;
    }
    System.out.println(this.name + " " + t_.num);
    }
    }
    }
    }
      

  20.   

    哈哈对对,没注意他最后一句话,纯属无心,嘿嘿
    不用wait()和notify()是可以的,你说的没错,至少我觉得,我上面说的也太绝对
      

  21.   

    其实,连synchronized都可以不用
    直接用线程安全的 AtomicInteger 就行了
    public static AtomicInteger num = new AtomicInteger(20);//线程安全的整数
    public static Random rd = new Random();//随机数public void sale(String name) {
    int n;
    while ((n = num.decrementAndGet()) >= 0) {//将整数减一并返回当前值
    System.out.println(name + " 运行到了num= " + n);
    try {
    Thread.sleep(rd.nextInt(20)+1);//随机休眠 1-20毫秒
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
      

  22.   

    Thread t1=new Thread(new ThreadTestNum());
    Thread t2=new Thread(new ThreadTestNum());
    Thread t3=new Thread(new ThreadTestNum());
    Thread t4=new Thread(new ThreadTestNum());问题很大,你应该只要一个ThreadTestNum tt = new ThreadTestNum()实例,,t1,t2,t3,t4中改成tt,