The “thread-safe” question is “thread-safe”?

In fact, “thread-safe” does not mean thread safety, but memory safety. Why is that? It has to do with the operating system.

Today’s major operating systems are multitasking, meaning that multiple processes are executing at the same time. Therefore, to ensure security, each process can only access its own memory space, not others’ space, which is guaranteed by the operating system.

Each process has a common area of memory: the heap (memory). All threads in the process can access this area, so this is a security risk. Suppose a thread gets tired in the middle of working on its own task, takes a break, comes back and tries to pick up where it left off, only to find that the data has been modified instead of the way it left it. This is because it may have been modified by another thread.

So, thread-safe means that data in heap memory is at risk of being modified by other threads without limitation because it can be accessed by any thread.

So how do we solve this thread safety problem? The following analyzes several solutions for different emphases.

Private property, please do not view

As mentioned earlier, the operating system assigns each process its own memory space, and each thread in the process has its own memory space, usually called stack memory, that other threads have no access to.

More common are local variables. This data is used by only one thread, and it is put into the stack memory of the thread that no other thread can manipulate or need to manipulate.

double avgScore(double[] scores) {
    double sum = 0;
    for (double score : scores) {
        sum += score;
    }
    int count = scores.length;
    double avg = sum / count;
    return avg;
}
Copy the code

The variables sum, count, and AVg are all local variables that are allocated to the thread’s stack. Given that there is a thread T1 executing the method, these variables are allocated to T1’s stack memory. Similarly, thread T2 will also allocate these variables in the stack memory of thread T2.

As you can see, local variables are allocated in stack memory for each thread, and only the thread is allowed to access them. Other threads do not know about them at all. This is the private property of each thread that no one else knows about. It can also be interpreted as: the “location” of the object is known only to you, so it is safe.

There is no fight, there is no grab

The above analysis shows that things in the “private location” of the program are safe, but not everything is private. In order to improve utilization, there is always something that needs to be placed in the public area. So how do you keep things safe in public areas? It’s simple. Everyone has his share and plays his own, so they don’t fight over it.

class StudentAssistant {

    ThreadLocal<String> realName = new ThreadLocal<>();
    ThreadLocal<Double> totalScore = new ThreadLocal<>();

    String determineDegree(a) {
        double score = totalScore.get();
        if (score >= 90) {
            return "A";
        }
        if (score >= 80) {
            return "B";
        }
        if (score >= 70) {
            return "C";
        }
        if (score >= 60) {
            return "D";
        }
        return "E";
    }

    double determineOptionalcourseScore(a) {
        double score = totalScore.get();
        if (score >= 90) {
            return 10;
        }
        if (score >= 80) {
            return 20;
        }
        if (score >= 70) {
            return 30;
        }
        if (score >= 60) {
            return 40;
        }
        return 60; }}Copy the code

The student helper class has two member variables, realName and totalScore, both of type ThreadLocal. Each thread makes a copy of it at run time and stores it locally.

T1 Thread is running Thread 90 and Thread 90, so these two data are stored in the T1 Thread object (Thread instance object) member variables. If the T2 Thread is running at the same time, it is “Thursday” and “85”, then “Thursday” and “85” are stored in the T2 Thread object (Thread instance object).

The Thread class has a member variable, similar to a Map, that is used to store data of type ThreadLocal. In terms of logical dependencies, these ThreadLocal data are at the member variable level of the Thread class. From the “location” point of view, these ThreadLocal data are allocated in the heap memory of the common area.

Each thread claims 1 copy of the data in the heap. At the same time, each thread can only use its own copy and cannot affect others’ copy.

It is important to note that these N pieces of data are stored in the common area of the heap, often referred to as “thread local” in terms of logical dependency, which corresponds to the thread, as if it has become its own “territory”. In fact, in terms of the “location” of the data, it is all in common heap memory, but it is claimed by the thread.

Say the important things three times. Say the important things three times. Say the important things three times.

ThreadLocal makes N copies of a data set, and each thread claims one copy.

Can be far view and not obscene play yan

According to our understanding, things placed in public areas are always a security risk, not necessarily absolute security. However, there are exceptions: if a very large object is left on the street and no one can handle it, it will be safe.

In the program, we consider this situation to be: only read, not write. That is, it can only be read, not modified. In fact, it refers to constants or read-only variables, they are safe for multithreading, can not be changed.

class No1 {

    final double passScore = 60;
}
Copy the code

For example, a student’s score is preceded by a final modifier so that no thread can touch it. Well, that makes it safe.

summary

The above analysis is the ideal situation, when the accident occurs, we also have other solutions, how to predict the future, and listen to the next time