Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中相对于单个线程同步一组多线程_Java_Multithreading_Synchronization_Deadlock - Fatal编程技术网

如何在Java中相对于单个线程同步一组多线程

如何在Java中相对于单个线程同步一组多线程,java,multithreading,synchronization,deadlock,Java,Multithreading,Synchronization,Deadlock,假设我有一个名为myList的arraylist线程,所有这些线程都是用实现Runnable接口的myRunnable类的实例创建的,也就是说,所有线程共享相同的代码,以便在myRunnable的run()方法中执行。现在假设我有另一个名为singleThread的线程,它是用实现Runnable接口的otherRunnable类的实例创建的 我必须为这些线程解决的同步化挑战如下:我需要myList中的所有线程执行它们的代码,直到某一点。一旦到了这一点,他们就应该睡觉了。一旦myList中的所有

假设我有一个名为myList的arraylist线程,所有这些线程都是用实现Runnable接口的myRunnable类的实例创建的,也就是说,所有线程共享相同的代码,以便在myRunnable的run()方法中执行。现在假设我有另一个名为singleThread的线程,它是用实现Runnable接口的otherRunnable类的实例创建的

我必须为这些线程解决的同步化挑战如下:我需要myList中的所有线程执行它们的代码,直到某一点。一旦到了这一点,他们就应该睡觉了。一旦myList中的所有线程都处于睡眠状态,那么应该唤醒singleThread(singleThread已经处于睡眠状态)。然后单线程执行它自己的东西,当它完成时,它应该睡眠,myList中的所有线程都应该被唤醒。假设代码被包装在while(true)中,所以这个过程必须一次又一次地发生

下面是我刚才描述的情况示例,包括解决同步问题的尝试:

class myRunnable extends Runnable
{
  public static final Object lock = new Object();
  static int count = 0;

  @override
  run()
  { 
     while(true)
     {
        //do stuff
        barrier();
        //do stuff
     }
  }

  void barrier()
  {
     try {
       synchronized(lock) {
          count++;
          if (count == Program.myList.size()) {
             count = 0;
             synchronized(otherRunnable.lock) {           
                otherRunnable.lock.notify();
             }
          }
          lock.wait();
       }
     } catch (InterruptedException ex) {}
  }
}

class otherRunnable extend Runnable
{
   public static final Object lock = new Object();

   @override
   run()
   {
     while(true)
     {
       try {
         synchronized(lock) {
            lock.wait();
       } catch (InterruptedException ex) {}

       // do stuff

       try {
         synchronized(myRunnable.lock) {
           myRunnable.notifyAll();
       }
     }
   }        
}

class Program
{
  public static ArrayList<Thread> myList;

  public static void main (string[] args)
  {
     myList = new ArrayList<Thread>();

     for(int i = 0; i < 10; i++)
     {
        myList.add(new Thread(new myRunnable()));
        myList.get(i).start();
     }
     new Thread(new OtherRunnable()).start();
  }
}
类myRunnable扩展了Runnable
{
公共静态最终对象锁=新对象();
静态整数计数=0;
@凌驾
运行()
{ 
while(true)
{
//做事
屏障();
//做事
}
}
空隙屏障()
{
试一试{
已同步(锁定){
计数++;
if(count==Program.myList.size()){
计数=0;
已同步(otherRunnable.lock){
otherRunnable.lock.notify();
}
}
lock.wait();
}
}catch(InterruptedException ex){}
}
}
类otherRunnable扩展Runnable
{
公共静态最终对象锁=新对象();
@凌驾
运行()
{
while(true)
{
试一试{
已同步(锁定){
lock.wait();
}catch(InterruptedException ex){}
//做事
试一试{
已同步(myRunnable.lock){
myRunnable.notifyAll();
}
}
}        
}
班级计划
{
公共静态数组列表myList;
公共静态void main(字符串[]args)
{
myList=新的ArrayList();
对于(int i=0;i<10;i++)
{
add(新线程(newmyrunnable());
myList.get(i.start();
}
新线程(新的OtherRunnable()).start();
}
}
基本上,我的想法是使用一个计数器来确保myList中的线程只是等待,除了增加计数器的最后一个线程,它将计数器重置为0,通过通知其锁来唤醒singleThread,然后最后一个线程也通过等待myRunnable.lock进入睡眠状态。在更抽象的级别上,我的方法是使用一些somyList中的线程在临界点停止执行,然后最后一个碰到障碍的线程唤醒singleThread并进入睡眠状态,然后singleThread完成任务,完成后唤醒障碍中的所有线程,以便它们可以再次继续

我的问题是我的逻辑中有一个缺陷(可能还有更多)。当最后一个遇到障碍的线程通知otherRunnable.lock时,有可能会发生立即上下文切换,在最后一个线程执行对myRunnable.lock的等待(并进入睡眠状态)之前将cpu交给单线程。然后,singleThread将执行其所有内容,并在myRunnable.lock上执行notifyAll,myList中的所有线程将被唤醒,但最后一个线程由于尚未执行其等待命令而遇到障碍。然后,所有这些线程将再次执行其内容并再次遇到障碍,但计数永远不会相等由于前面提到的最后一个线程最终会被再次调度并执行wait,因此,单线程也会在其第一行中执行wait,从而导致死锁,每个人都在睡觉


因此,我的问题是:为了实现前面描述的期望行为,但同时又以安全的方式避免死锁,同步这些线程的好方法是什么???

根据您的评论,听起来a完全符合您的需要。来自文档(我的重点):

一种同步辅助工具,允许一组线程都等待彼此到达一个共同的障碍点。在涉及固定大小的线程组的程序中,循环传送者很有用,这些线程偶尔必须等待彼此。该障碍被称为循环障碍,因为在等待的线程重新出现后,它可以重新使用租赁

不幸的是,我自己没有使用过它们,所以我不能给出它们的具体指针。我认为基本的想法是使用带有
barrierAction
的双参数构造函数来构造屏障。让
n
线程
等待()
此任务完成后,在此屏障上执行
屏障操作
,然后
n
线程将继续

从javadoc for
CyclicBarrier#await()

如果当前线程是最后一个到达的线程,并且构造函数中提供了非空的屏障操作,则当前线程在允许其他线程继续之前运行该操作。如果屏障操作期间发生异常,则该异常将在当前线程中传播,屏障将放置在b中罗肯州


太长了,读不下去了。你能给出一个更高层次的描述你正在试图解决的问题吗?-在 java。UTIL并发< /COD>已经有一个很好的解决方法。也许我的问题还不清楚,所以我将尝试用更简单的方式来解释它。我有N个线程和另一个线程X。我想知道一种实现以下行为的方法:F:irst n线程执行到关键代码行