首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

在Linux上多线程的有关问题

2012-10-30 
在Linux下多线程的问题最近做的程序出现了一个多线程的问题,肯定是同步引起的,但是我个人还是不太理解,因

在Linux下多线程的问题
最近做的程序出现了一个多线程的问题,肯定是同步引起的,但是我个人还是不太理解,因为同样一段代码在Windows下运行正常,在Linux下就处理一堆问题了。

程序思想是这样子的,有多个任务需要处理,每次主线程处理一个任务,并把这个任务分成多个子任务让子线程去处理。在主线程中启动多个子线程去做事情,并注册自己。主线程就不断的检查是所有线程已经注销了,子线程做完事情后,会向主线程销自己,然后结束。

代码如下:

public class TaskDispatchController{    Set threadSet = new HashSet();    /**    *  启动子线线程做事情    */    private void startThread()    {        //重用线程对象        ImportThread[] thread = importTool.getImportThread();        threadList = new ArrayList(thread.length);        for (int i = 0; i < thread.length; i++)        {            ImportThread impThread = thread[i];            //子线程注册自己            threadSet.add(impThread);            impThread.setController(this);            new Thread(impThread).start();        }        checkQuite();    }        /**    *  注销自己,并唤醒主线程检查是否可以退出    */    public synchronized void unregister(ImportThread thread)    {       threadSet.remove(thread);       notifyAll();    }    /**    *    */    private synchronized void checkQuite()    {        try        {            while (!threadSet.isEmpty())            {                wait();            }            backThread();        }        catch (InterruptedException e)        {            throw new ThreadOperationException("main thread exception", e);        }        finally        {            close();        }    }}public class ImportThread{    TaskDispatchController  taskDispatchController = null;    public void setController(TaskDispatchController  taskDispatchController )    {         this.taskDispatchController = taskDispatchController ;    }     public void run()     {if (taskDispatchController == null){    return;}         //做某事情         [b]taskDispatchController.doXXX();[/b]         while (true){    // do something         }         //执行完事情后结束release();     }               private void release()     {if (taskDispatchController != null){    taskDispatchController .unregister(this);}         [b]taskDispatchController == null;[/b]         }}




这段代码在Windows下,双核CPU的环境中做事不会出现错误,且可以启动多个子线程。但在Linux环境下,就启动一个子线程就会出问题,会出现死锁,并且是销在TaskDispatchController的startThread方法,感到很奇怪。

解决方法:随后,我将startThread线程,并标记为同步,并且要所有子线程启动后,子线程才能注销自己。以避免子线程跑得太快了,就结束自己了(这是领导认为的问题所在,但我个人不这么认为,看代码就明白了)。

修改了之后仍然出现死锁。原因是:在子线程run中调用taskDispatchController.doXXX()的时候报NullPointerException,导致子线程没有注销自己,主线程处于一直等待状态。

解决方法:因为我在线程结束的时候将taskDispatchController = null了(也不知道当时是怎么考虑的,其实没有必要设置为null),所以我将release方法中这一行删去。
并修改TaskDispatchController.unregister方法
  public synchronized void unregister(ImportThread thread)  {       threadSet.remove(thread);       thread.setController(null);       notifyAll();  }


现在程序在Linux下能正常运行,但其中的原因还是不得而知,希望哪位指点指点voliate boolea staredAll = false;Set threadSet = new HashSet(); /** * 启动子线线程做事情 */ private void startThread() { //重用线程对象 ImportThread[] thread = importTool.getImportThread(); threadList = new ArrayList(thread.length); for (int i = 0; i < thread.length; i++) { ImportThread impThread = thread[i]; //子线程注册自己 threadSet.add(impThread); impThread.setController(this); new Thread(impThread).start(); } startedAll= true; checkQuite(); } /** * 注销自己,并唤醒主线程检查是否可以退出 */ public synchronized void unregister(ImportThread thread) { try { while(!startedAll) { wait(); } } catch(InterruptedException e) { // doNothing } threadSet.remove(thread); notifyAll(); }

呵呵,当时做的时候还不怎么了解Concurrent,现在已经改了代码实现了,用上了这些feature,不过我不明白为什么在Liunx下面的运行,跑一个线程也会有问题,我猜是linux下的线程调度不太一样,想知道其中的原由,还请指点private void release() { if (taskDispatchController != null) { taskDispatchController .unregister(this); } <STRONG>taskDispatchController == null;</STRONG> }

修改之后为:
class ImportThread
private void release()   {       if (taskDispatchController != null)       {           taskDispatchController .unregister(this);       }      }

TaskDispatchController
     /**        *  注销自己,并唤醒主线程检查是否可以退出        */         public synchronized void unregister(ImportThread thread)          {            try         {              while(!startedAll)              {                  wait();              }          }          catch(InterruptedException e)          {              // doNothing          }       //将引用的controller置为null       threadSet.setController(null);           threadSet.remove(thread);             notifyAll();          }  


如此修改后,也不会有问题了。到底这多线程在linux和windows是上运行方式有什么差异呢,这是我最知道的问题 5 楼 dennis_zane 2008-09-12   从你的代码中没有看出为什么在同步后出现空指针,不过你的代码还是有问题,对startedAll变量的修改没有同步,也就是startThread方法需要同步,这个可能是你弄错了。jvm的不同实现,肯定依赖于平台,java对线程安全性的保证是基于java内存模型的,符合java内存模型的代码在各个平台上可以做到的一致,如果一开始就是错误的,在不同平台出现莫名其妙的问题在所难免。 6 楼 卒子99 2008-09-12   start方法就加了一个synchronized,上面没有写出来,不过现在看,当时一年前写的东西是有很多问题,确实多线程太复杂了,出错就报一些莫名其妙的问题,调试起来也很麻烦。看来要在设计的时候,特别注意这些问题,哈哈一条,不得已就不要用多线程了

热点排行