1

我正在使用信号量来强制我的程序中的一些顺序:我有一个主线程和一些在主线程中创建的子线程。在每一步的主线程中,都会打勾,然后我希望每个子线程一个接一个地运行。子线程的顺序并不重要,但我希望它们都在每个步骤中运行(并且每个步骤只运行一次)。我已经写了这段代码,但问题是在某些情况下,子线程的一步运行多次不让其他人有机会运行?!

主线程:

     Semaphore okToTick = new Semaphore(3);
     Semaphore okToWork = new Semaphore(0, true);

     int i = 0;

     new TestClass2(0, okToTick, okToWork);
     new TestClass2(1, okToTick, okToWork);
     new TestClass2(2, okToTick, okToWork);

     while(true){

        okToTick.acquire(3);

        System.out.printf("\clock : %s\n", i++);


        okToWork.release(3);

     }

和子线程的 run() :

    semaphores here, passed by cnstr() 
    ID = //passed in by cnstr()    
    isBusy = false; 
    ----------------------------------
    try{
        while(true){

            okToWork.acquire();

            if(!isBusy){
                System.out.println("inside sub " + ID);
                isBusy = true;
            }


            okToTick.release();

        }

    }
    catch(Exception e){}

我想要这个结果:

  clock : 0
  inside sub 1
  inside sub 0
  inside sub 2

  clock : 1

  clock : 2
  ...

但有时我会得到这个:

  clock : 0
  inside sub 1

  clock : 1
  inside sub 0
  inside sub 2

  clock : 2
  ...
4

3 回答 3

7

我认为您正在寻找CyclicBarrier

一种同步辅助工具,它允许一组线程相互等待以达到共同的障碍点。CyclicBarriers 在涉及固定大小的线程组的程序中很有用,这些线程组必须偶尔相互等待。屏障被称为循环的,因为它可以在等待线程被释放后重新使用。

于 2012-12-22T13:20:51.947 回答
1

在您的情况下,一个线程可以 在其他线程甚至有机会启动之前多次获取okToWork和释放,即。okToTick线号 1最多可以做3次 okTowork.acquire()->okToTick.release()在其他人之前。

您也只为每个线程打印inside sub x一次,因为您从不重置isBusy标志。

您需要区分它们,使用 a 的最简单方法是给每个线程Semaphore一个不同的值。okToTick Semaphore

于 2012-12-22T13:47:50.530 回答
0

问题是您的“子线程”可能从信号量获得多个许可,并且您没有在输出中意识到它,因为“内部子”输出仅打印一次(如果您会看到它多次去掉if(!isBusy)周围的它)。如果您不希望每个“子线程”获得多个许可,请删除外部while(true)循环。

    okToWork.acquire();

    //if(!isBusy){ Removed to show when this sub-thread is actually acquiring permits
        System.out.println("inside sub " + ID);
    //    isBusy = true;
    //}


    okToWork.release();
于 2012-12-22T13:41:16.080 回答