CyclicBarrier代码不起作用?

时间:2013-06-16 16:17:58

标签: multithreading java.util.concurrent cyclicbarrier

我从oracle页面获得了CyclicBarrier代码以便更多地了解它。我修改了它,现在有一个疑问。 下面的代码没有终止,但如果我取消注释Thread.sleep条件,它工作正常。

import java.util.Arrays;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

class Solver {
    final int N;
    final float[][] data;
    boolean done = false;
    final CyclicBarrier barrier;

    class Worker implements Runnable {
        int myRow;

        Worker(int row) {
            myRow = row;
        }

        public void run() {
            while (!done) {
                processRow(myRow);

                try {
                    barrier.await();
                } catch (InterruptedException ex) {
                    return;
                } catch (BrokenBarrierException ex) {
                    return;
                }
            }
            System.out.println("Run finish for " + Thread.currentThread().getName());
        }

        private void processRow(int row) {

            float[] rowData = data[row];

            for (int i = 0; i < rowData.length; i++) {
                rowData[i] = 1;
            }

            /*try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
            done = true;
        }
    }

    public Solver(float[][] matrix) {
        data = matrix;
        N = matrix.length;
        barrier = new CyclicBarrier(N, new Runnable() {
            public void run() {
                for (int i = 0; i < data.length; i++) {
                    System.out.println("Data " + Arrays.toString(data[i]));
                }

                System.out.println("Completed:");
            }
        });
        for (int i = 0; i < N; ++i)
            new Thread(new Worker(i), "Thread "+ i).start();
    }
}

public class CyclicBarrierTest {
    public static void main(String[] args) {

        float[][] matrix = new float[5][5];

        Solver solver = new Solver(matrix);
    }
}

为什么在上面的代码中需要Thread.sleep?

1 个答案:

答案 0 :(得分:1)

我没有运行您的代码,但可能存在竞争条件,这是一个揭示它的场景:

  • 启动第一个线程,它会在一定时间内运行,足以完成 processRow 方法调用,因此它将 done 设置为true并且然后等待障碍

  • 其他线程开始,但他们发现所有“已完成”因此他们不会进入循环而他们永远不会等待障碍 ,并直接结束

  • 屏障永远不会被激活,因为N个线程中只有一个已经到达

  • <强>死锁

为什么使用睡眠

  • 当其中一个线程开始进入睡眠状态时允许其他线程工作,然后将工作标记为“已完成

  • 其他线程有足够的时间工作,并且自己可以到达障碍

  • 2秒足以让5个线程结束不超过10毫秒的处理

但是请注意,如果你的系统被加载了,它可能会陷入僵局:

  • 第一个帖子开始入睡

  • 操作系统调度程序允许其他应用程序超过2秒

  • OS调度程序返回到您的应用程序,线程调度程序再次选择第一个线程,让它终止,将 done 设置为true

  • 这里又是第一个场景=&gt; 死锁也是

可能的解决方案(抱歉未经测试):

执行/同时循环更改您的while循环:

do
{
    processRow(myRow);

    ...
}
while (!done);