Java Fork/Join Does it work the same as C Fork?

Asked

Viewed 630 times

4

Discussing with a friend about a matrix calculation solution that we are developing, the following question arose.

Java Fork/Join Framework operation is equal to C?

Reading a little I could not understand very well the functioning of C. Someone could help me in this?

2 answers

2

The Fork is a function that is a system call. That is, it invokes the operating system to do some task that the user cannot. In this case, Fork is used to create a new process on Unix-like systems, and this can only be done via Fork.

When a process is created through Fork, we say that this new process is the child, and the parent process is the one that used Fork.

To use the process creation system call, simply write Fork(), without passing any argument. In doing so, the Operating System takes care of the rest, and returns a number. This number is pid (process Identification, or process identifier), and each process has a different value of pid, it’s like RG, the identification of each process.

However, by storing this Fork function return in a name variable pid of the kind pid_t, we see that this pid number has a special behavior:

Within the child process, pid has value 0.

Within the parent process, pid has the value of the child process.

To fork() returns a negative value if any error has occurred.

Thus, to create a program and differentiate the parent process from the child, we need only make a test with this return value of fork(). First, we test whether the fork() was successful. Then we do if (pid == 0), and this is only true in the child process. That is, everything within that if You’re only gonna be executed for the lawsuit, son. And if this conditional test is false, it is because the process in effect is the father. So, within the Else, put what will be executed only in the parent process.

An example of how to implement a Fork in C:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
    int i;
    pid_t pid;

    if ((pid = fork()) < 0) /*Se ocorer um erro*/
    {
        perror("fork");
        exit(1);
    }

    /**O getpid() retorna o pid do processo em execução.**/
    if (pid == 0)
    {
        //O código aqui dentro será executado no processo filho
        printf("pid do Filho: %d\n", getpid());
    }
    else
    {
        //O código neste trecho será executado no processo pai
        printf("pid do Pai: %d\n", getpid());
    }

    printf("Esta regiao sera executada por ambos processos\n\n");
    scanf("%d", &i);
    exit(0);
}

The conclusion is that the goal of Fork is to create a child process from the parent process, and work with both simultaneously and using either the same variables or your own, so you can make your application able to perform more than one task.

PS: Both libraries are required sys/types.h and unistd.h Unix, so you can work with Fork.

Source.

  • The whole problem is that we’re trying to implement the equivalent in Java, so Doubt.

  • If you want to ask another question about how to implement Fork in java or you can check here the documentation for java https://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html. But I suggest you ask another question msm.

1

From what I read of tutorial, is a little different.

In C, when you do Fork, you have 2 processes, a father and a son. In possession of the child’s pid, the parent process can do the Join, when the child process ends.

In Java, the algorithm is similar, but the operation for the Operating System is different. The algorithm is

se (a parte de trabalho for pequena o suficiente)
   faça o que tem que fazer
caso contrário
   divida o meu trabalho em duas partes
   execute as duas partes e espere pelo resultado

Example taken from University of Washington:

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

class Sum extends RecursiveTask<Long> {
    static final int SEQUENTIAL_THRESHOLD = 5000;

    int low;
    int high;
    int[] array;

    Sum(int[] arr, int lo, int hi) {
        array = arr;
        low   = lo;
        high  = hi;
    }

    protected Long compute() {
        if(high - low <= SEQUENTIAL_THRESHOLD) {
            long sum = 0;
            for(int i=low; i < high; ++i) 
                sum += array[i];
            return sum;
         } else {
            int mid = low + (high - low) / 2;
            Sum left  = new Sum(array, low, mid);
            Sum right = new Sum(array, mid, high);
            left.fork();
            long rightAns = right.compute();
            long leftAns  = left.join();
            return leftAns + rightAns;
         }
     }

     static long sumArray(int[] array) {
         return ForkJoinPool.commonPool().invoke(new Sum(array,0,array.length));
     }
}

In this example, you sum the elements of an Array. If the array has more than 5000 elements, the task will be divided. The method compute implements the described pseudo-code.

Ordering example:

static class SortTask extends RecursiveAction {
    final long[] array; final int lo, hi;
    SortTask(long[] array, int lo, int hi) {
        this.array = array; this.lo = lo; this.hi = hi;
    }
    SortTask(long[] array) { this(array, 0, array.length); }
    protected void compute() {
        if (hi - lo < THRESHOLD)
            sortSequentially(lo, hi);
        else {
            int mid = (lo + hi) >>> 1;
            invokeAll(new SortTask(array, lo, mid),
                new SortTask(array, mid, hi));
            merge(lo, mid, hi);
        }
    }
    // implementation details follow:
   static final int THRESHOLD = 1000;
   void sortSequentially(int lo, int hi) {
       Arrays.sort(array, lo, hi);
   }
   void merge(int lo, int mid, int hi) {
       long[] buf = Arrays.copyOfRange(array, lo, mid);
       for (int i = 0, j = lo, k = mid; i < buf.length; j++)
           array[j] = (k == hi || buf[i] < array[k]) ?
               buf[i++] : array[k++];
   }
}

First you have to choose the type of Task. Are two options:

  • RecusiveTask: returns a result after Fork
  • ActionTask: does not return a result after Fork

Second you have to implement the Compute method by following the pseudo-algorithm, using invokeAll, compute, fork and join.

Finally, you have to use a thread pool called ForkJoinPool. I saw at least two ways:

ForkJoinPool.commonPool().invoke(task);

or

ForkJoinPool pool = new ForkJoinPool();
pool.invoke(task);

At the bottom of the cloths, java.util.Arrays.parallelSort uses Fork/Join API.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.