java thread synchronization

Keywords: Java git

Why Thread Synchronization

When we have multiple threads to operate on the same resource, such as a file, we can not allow multiple threads to operate on the file at the same time. Because when a file is shared, multiple operations will conflict. I believe that people who have used git for team development will have a profound experience.

At this point, we need to introduce the synchronization mechanism of threads.

The so-called synchronization refers to one execution, that is, queuing, several threads queuing to execute, so that there is a first-come-first-come relationship between threads. In this way, there will be no competition and no conflict.

Problem description

A program with two threads. The first thread calculates the even number and number between 2 and 1000, and the second thread calculates the even number and number between 1000 and 2000.

Preliminary realization

First, we design the implementation method according to the topic.

1. Define two threads. Here you define your own thread class, and then set the start and end of computing even numbers.
2. Achieve even and even numbers in the given range
3. Execution threads

You can see that the implementation is simple. The preliminary realization is as follows:

1. Define your own thread class:

public class MyTread extends Thread {
    private int begin;          // Scope start
    private int end;            // End of scope

    public MyTread(int begin, int end) {
        this.begin = begin;
        this.end = end;
    }
}

2. Realize the calculation of even number and even number

@Override
public void run() {
    this.getEven(begin, end);
}

// Get even numbers and numbers
private void getEven(int begin, int end) {
    int count = 0;
    System.out.println(begin + "~" + end + "The even number between them is:");
    if (begin % 2 != 0) {
        begin += 1;
    }

    for (; begin <= end; begin += 2) {
        System.out.print(begin + " ");
        count++;
    }

    System.out.println();
    System.out.println("Even numbers are:" + count);
}

3. Initialize threads and run them

public static void main(String[] args) {
    MyTread tread1 = new MyTread(2, 500);
    MyTread tread2 = new MyTread(500, 1000);
    tread1.start();
    tread2.start();
}

Note: In order to show the effect behind, the number range is reduced.

Look at the results:

It doesn't seem to be the effect we want. We want this effect:

We want the even and even numbers of each part to be together, but the effect of our implementation is really confusing.

Procedural Perfection

To solve the above problems, we need to use the thread synchronization we started talking about.

According to our introduction at the beginning, we found that one condition for synchronization is to have a shared resource. So what is this shared resource in our code? No, it seems. So create one first.

1. Establishing Shared Resources

Our shared resources here can be exactly the same object, so we set up another class to illustrate shared resources.

public class Even {}

2. Then, a method to calculate even numbers in shared classes is established.

public class Even {
    /**
     * Get even numbers and numbers in a range
     * @param begin Statistics start
     * @param end   End of Statistics
     */
    public synchronized void getEven(int begin, int end) {
        int count = 0;
        System.out.println(begin + "~" + end + "The even number between them is:");
        if (begin % 2 != 0) {
            begin += 1;
        }

        for (; begin <= end; begin += 2) {
            System.out.print(begin + " ");
            count++;
        }

        System.out.println();
        System.out.println("Even numbers are:" + count);
    }
}

Careful people will find that this method is a little different from the way we first wrote it. It has one more keyword: synchronized. With this keyword, we can synchronize threads while executing methods.

3. Finally, the shared method is called in the thread.

public class MyTread extends Thread {
    Even even;
    
    @Override
    public void run() {
        even.getEven(begin, end);
    }
}

At this time, let's do it again:

We achieved the desired results.

Finally, complete code is attached:

/**
 * Even numbers
 */
public class Even {
    /**
     * Get even numbers and numbers in a range
     * @param begin Statistics start
     * @param end   End of Statistics
     */
    public synchronized void getEven(int begin, int end) {
        int count = 0;
        System.out.println(begin + "~" + end + "The even number between them is:");
        if (begin % 2 != 0) {
            begin += 1;
        }

        for (; begin <= end; begin += 2) {
            System.out.print(begin + " ");
            count++;
        }

        System.out.println();
        System.out.println("Even numbers are:" + count);
    }
}

public class MyTread extends Thread {
    Even even;
    private int begin;          // Scope start
    private int end;            // End of scope

    public MyTread(Even even, int begin, int end) {
        this.even = even;
        this.begin = begin;
        this.end = end;
    }

    @Override
    public void run() {
        even.getEven(begin, end);
    }

    public static void main(String[] args) {
        Even even = new Even();
        MyTread tread1 = new MyTread(even, 2, 500);
        MyTread tread2 = new MyTread(even, 500, 1000);
        tread1.start();
        tread2.start();
    }
}

Posted by qbox on Tue, 29 Jan 2019 12:18:15 -0800