繁体   English   中英

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

[英]Static variable usage while using Fork-Join

问题陈述:-//这是一个示例,实际数组大小非常大

假设有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类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. 假设分叉1计算静态变量aa [2],并且假设当分叉2将要计算aa [2]时,此分叉2能否获得由fork1计算的值aa [2]或将单独计算?

  2. 据我了解,在某些情况下fork 2可以轻松访问fork1的aa,假设fork 2要计算aa [3],它可以获取已经由fork 1计算的值。但是问题在于,假设fork 1将尝试计算aa [4],要计算aa [4],需要aa [3],叉子1已经计算过了,但是如果叉子1尝试获取aa [3],它是否有可能,但是偶然地它获得了aa [3]的访问权没有计算的叉子1的...再次造成混乱。

我很困惑,请加入fork

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

  1. 假设分叉1计算静态变量aa [2],并且假设当分叉2将要计算aa [2]时,此分叉2能否获得由fork1计算的值aa [2]还是将其单独计算?

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

  1. 据我了解,在某些情况下fork 2可以轻松访问fork1的aa,假设fork 2要计算aa [3],它可以获取已经由fork 1计算的值。但是问题在于,假设fork 1将尝试计算aa [4],要计算aa [4],需要aa [3],叉子1已经计算过了,但是如果叉子1尝试获取aa [3],它是否有可能,但是偶然地它获得了aa [3]的访问权没有计算的叉子1的...再次造成混乱。

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

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

在某些情况下,您可能有不同的线程并行计算数组的不相交部分。 但是,由于数据之间的依赖性,问题中提出的计算不适合该计算。 由于在计算前一个索引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提供实例(因此他们共享它)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM