日期:2014-05-20  浏览次数:20599 次

双核CPU上运行Notify 与wait的通知丢失现象
大家好,最近写一个多线程程序,用到了wait/notify ,做了个小实验,发现在双核和单核上跑的结果有很大差异

单核上,如java手册上写的一样,双核,则notify不到执行wait的部分,难道是wait在实现上不支持多cpu的问题(如操作系统教材中所说,有些利用中断的原语不能用于多核?)请大家指正

代码如下:
Java code
package thread1;
// this program is puzzle when run on 2 core ,I do not know why ,it just
// do not stop
class ThreadA {
  public static void main(String[] args) {
    ThreadB b = new ThreadB();
    b.start();
    System.out.println("b is start....");
    synchronized (b)// 括号里的b是什么意思,起什么作用?
    {
      try {
        System.out.println("Waiting for b to complete...");
        b.wait();// 这一句是什么意思,究竟让谁wait?
        System.out.println("Completed.Now back to main thread");
      } catch (InterruptedException e) {
        System.out.println("InterruptedException");
      }
    }
    System.out.println("main:Total is :" + b.total);
  }
}

class ThreadB extends Thread {
  int total;

  public void run() {
    synchronized (this) {
      System.out.println("ThreadB is running..");
      for (int i = 0; i < 10; i++) {
        total += i;
        System.out.println("total is " + total);
      }
      notify();
      /*
       * try { System.out.println("b is waiting" ); wait();
       *  } catch (InterruptedException e) { System.out.println("InterruptedException"); }
       */
    }
    System.out.println("AFTER notify");
    System.exit(0);
  }
}


------解决方案--------------------
学习, 帮顶了
------解决方案--------------------
synchronized (b)// 括号里的b是什么意思,起什么作用? 
--------------括号里的b是监听器对象,这个对象是可以随意的!但是涉及到多个synchronized时,括号里的对象要保持一致,只有保持一致了,才能够达到想要的同步.

b.wait();// 这一句是什么意思,究竟让谁wait? 
肯定是让b去wait啊.
  
你这个程序我觉得错误就是根本没有了解synchronized的用法啊. 对象没有一致,也既是监听器对象没有一致.导致出现结果在双核和单核上运行的差异,其实你在单核上运行2次的结果也应该是不一样的.因为没有达到同步,结果应该就是随机的.


------解决方案--------------------
synchronized (b)//增加了个锁,锁定了对象b,在同一个类实例中,是线程安全的,但不同的实例还是不安全的。
b.wait();// 让b线程wait
------解决方案--------------------
我觉得你这个程序就是正确的,反正我没看出程序本身哪里有问题
------解决方案--------------------
你可以在b所在的thread启动代码后面让主线程sleep下不就是了
sleep()的时间你可以自己在()里面设置,是以毫秒为单位的
------解决方案--------------------
探讨
你可以在b所在的thread启动代码后面让主线程sleep下不就是了
sleep()的时间你可以自己在()里面设置,是以毫秒为单位的

------解决方案--------------------
学习
------解决方案--------------------
学习了,双核是偶也遇到这个问题
------解决方案--------------------
不是双核的问题,而的你的线程死锁的问题

lz改用一下jdk自带的线程池可以解决这样的问题

根据cpu数量乘以每个cpu的线程数来创建池


------解决方案--------------------
把原始程序改成如下形式,单CPU机器上运行也不能正常退出了。
Java code

public class ThreadTest
{
    public static void main(String[] args)
    {
        ThreadB b = new ThreadB();
        b.start();
        System.out.println("b is start....");
        try
        {
            Thread.sleep(2000);//没有这个的话,单CPU上运行,成功的可能性很大
        }
        catch (InterruptedException ex)
        {
            ex.printStackTrace();
        }
        synchronized (b)// 括号里的b是什么意思,起什么作用?
        {
            try
            {
                Thread.sleep(2000);
                System.out.println("Waiting for b to complete...");
                b.wait();// 这一句是什么意思,究竟让谁wait?
                System.out.println("Completed.Now back to main thread");
            }
            catch (InterruptedException e)
            {
                System.out.println("InterruptedException");
            }
        }
        System.out.println("main:Total is :" + b.total);
    }
}

class ThreadB extends Thread
{
    int total;

    public void run()
    {
        synchronized (this)
        {
            System.out.println("ThreadB is running..");

            for (int i = 0; i < 100; i++)
            {
                total += i;
                System.out.println("total is " + total);
            }
            notify();
            /*
             * try { System.out.println("b is waiting" ); wait();
             *  } catch (InterruptedException e) {
             * System.out.println("InterruptedException"); }
             */
        }
        System.out.println("AFTER notify");
    }
}