简体   繁体   中英

Static variable usage while using Fork-Join

Problem statement:- //This is a example, Actual array size is very large

suppose there is 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];
    }
}

And 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();
        }
    }
}

Doubt?

  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??

  2. 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.

I am very puzzle by fork join kindly help

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?

  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?

Supposing that the two B tasks run in different threads -- over which you elect not to exercise any control -- those two threads are accessing the same element of the same array object without any synchronization. Either thread can read the value written by the other. Moreover, they may read a different value if they access that array element again. The program is not correctly synchronized and therefore there is no guarantee of sequential consistency.

  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.

Yes, you judge rightly -- both about possible behaviors and about it being 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?

Under some circumstances, you might have different threads compute disjoint sections of the array in parallel. The computation presented in the question is not amenable to that, however, because of the dependencies between the data. Because no element past index 1 can be computed before the previous 2 have been computed, computation of the elements needs to be serialized, one way or another. You cannot achieve that any faster than by devoting a single thread to the job.

After such a computation is completed, you can share the initialized array among threads, provided that they synchronize with the completion of the computation one way or another. Additional synchronization requirements apply if any of the threads modify the array after the initial computation is complete.

Your particular case is a bit tricky, because few actions with synchronization significance are present. In particular, your array elements are not (and cannot be) final , and you cannot be confident that the threads in which your tasks run are started only when you fork() ; if you had the latter then everything the main thread did before would automatically synchronize with the work of the tasks. As it is, you might do something like this:

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();
        }
    }
}

Note here that the main thread creates an instance of A and initializes it before forking any tasks. It provides that instance to each B (thus they share it).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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