使用 Fork-Join 时静态变量的使用

Static variable usage while using Fork-Join

问题陈述:- //This is a example, Actual array size is very large

假设有class A

public class A{
    public static int aa[]=new int[5];
    public computeaa(){
         for(int i=0;i<5;i++) 
          aa[i] = useaa(i);
    }
     //this below function can compute aa[i] value
    public int useaa(int i){
           if(i<=0)
                return 1;
           if(aa[i]!=0)
               return aa[i];
           else 
              return useaa[i-1]+useaa[i-2];
    }
}

和 RecursiveAction class B

@Override
protected void compute() {
    // TODO Auto-generated method stub
    A z=new A();
    A.computeaa();
}
public static void main(String[] args) {
   List<B> tasks =new ArrayList<B>();
   for(int i=1; i<=2; i++){
      //There is 2 fork will created 
        B =new B();
        tasks.add(B);
        B.fork();
    }
    if (tasks.size() > 0) {
        for (B task : tasks) {
            task.join();
        }
    }
}

有疑问?

  1. 假设fork 1计算静态变量aa[2],假设fork 2去计算aa[2]时,这个fork 2能不能得到fork1计算出来的值aa[2]还是单独计算??

  2. 根据我的理解,fork 2在某些情况下很容易访问fork1的aa,假设fork 2想要计算aa[3],它可以得到fork 1已经计算出的值。但是问题假设当 fork 1 将尝试计算 aa[4] 时,为了计算 aa[4],它需要 aa[3],其中 fork 1 已经计算但是如果 fork 1 尝试获取 aa[3] 是否有可能,但是通过它有机会获得未计算的 fork 1 的 aa[3] 的访问权限...再次造成混乱。

我很不解 fork join 请大家帮忙

有一个简单的问题,我想计算一些由同一个 class 使用的数组,但是在创建多个对象时我想使用由其他对象计算的相同数组,以便我的减少了计算时间。
我怎样才能将该数组复制或获取到另一个对象,以便该对象不需要计算?

  1. suppose fork 1 computes static variable aa[2], and suppose when fork 2 going to computes aa[2], can this fork 2 get the value aa[2] which was computed by fork1 or it will compute seperately?

假设两个 B 任务 运行 在不同的线程中——您选择不对其进行任何控制——这两个线程正在访问同一个数组对象的同一个元素,而没有任何同步。任何一个线程都可以读取另一个线程写入的值。此外,如果他们再次访问该数组元素,他们可能会读取不同的值。该程序未正确同步,因此无法保证顺序一致性。

  1. By my understanding fork 2 in some cases easily access fork1's aa, suppose fork 2 wanted to compute aa[3],It can get the value which was already computed by fork 1. But the problem is suppose when fork 1 will try to compute aa[4], for calculating aa[4], it need aa[3], which fork 1 already computed but can it possible if fork 1 try to get aa[3], but by chance it get the access of aa[3] of fork 1 which was not calculate... again it creating a mess.

是的,您的判断是正确的——无论是关于可能的行为还是关于它是一团糟。

There is simple problem, i want to compute some array which is used by same class, but while creating more then one object i want to use the same array which was computed by other object so that my computation time reduced. How can i copy or get that array to another object, so that this object doesn't need to compute?

在某些情况下,您可能会让不同的线程并行计算数组的不相交部分。然而,由于数据之间的依赖关系,问题中提出的计算不适合于此。因为在计算前一个 2 之前不能计算索引 1 之后的元素,所以需要以某种方式对元素的计算进行序列化。您无法通过将单个线程用于作业来更快地实现这一目标。

这样的计算完成后,您可以在线程之间共享初始化的数组,前提是它们以某种方式与计算的完成同步。如果任何线程在初始计算完成后修改数组,则适用额外的同步要求。

您的具体情况有点棘手,因为很少有具有同步意义的操作存在。特别是,您的数组元素不是(也不可能是)final,并且您不能确信您的任务 运行 所在的线程仅在您 fork() 时启动;如果你有后者,那么主线程之前所做的一切都会自动与任务的工作同步。实际上,您可以这样做:

public class A {
    // not static:
    public int aa[] = new int[5];

    public void computeAa() {
        aa[0] = 1;
        aa[1] = 1;

        for (int i = 2; i < aa.length; i++) {
            aa[i] = aa[i - 1] + aa[i - 2];
        }
    }

    public int getAa(int i) {
        return (i < 0) ? 1 : aa[i];
    }
}

public class B extends RecursiveAction {

    private A myA;

    public RecursiveAction(A a) {
        myA = a;
    }

    @Override
    protected void compute() {
        synchronized (myA) {
            // ensure that myA's initialization is complete
            while (myA.aa[0] == 0) {
                // not yet initialized
                myA.wait();
            }
        }
        // ... do something with myA (without modifying it) ...
    }

    public static void main(String[] args) {
       A theA = new A();

       synchronized(theA) {
           // synchronize the initialization of theA, because other threads will
           // check it
           theA.computeAa();

           // wake up any threads waiting on the initialization
           theA.notifyAll();
       }

       List<B> tasks = new ArrayList<B>();

       for(int i = 1; i <= 2; i++){
          //There is 2 fork will created 
            B = new B(theA);
            tasks.add(B);
            B.fork();
        }

        for (B task : tasks) {
            task.join();
        }
    }
}

注意,主线程创建了一个 A 的实例,并在派生任何任务之前对其进行初始化。它为每个 B 提供该实例(因此他们共享它)。