Java Concurrency (b): how to ensure atomicity shared variables?

Thread safety is our time to making Java Concurrency must first consider clearly a problem. This class in single-threaded environment is not a problem, then we can make sure it shows you the correct behavior in the case of multiple concurrent threads?

I am the person, in the absence sideline, wholeheartedly in the work above, the processing of very handy, the mentality has remained good; but then had sideline, mind becomes like a roller coaster. Sideline earning more than the main industry of the time, people are particularly excited, like to play with blood, like; sideline delay opened up the situation when the person becomes constant state of anxiety.

If I can only be a single-threaded, the main industry and sideline parallel multi-threaded mode is turned on, when I became insecure in particular, has been greatly improved than before in spite of the overall income is not a sideline.

How I let myself be a sense of security, I did not want to know (if you have a good method, be sure to tell me). But how to make a class in a multi-threaded environment is safe, there are three rules, let me tell you:

1, the shared state variable is not between threads. 2, the state variables to immutable. 3, using synchronized access state variables.

Then you may want to ask, what state variables are?

Let's look at a class variable does not state it, the code sample below.

class Chenmo {
    public void write() {
        System.out.println("我寻了半生的春天,你一笑便是了。");
    }
}
复制代码

Chenmo This class is no state variables, it is only one way, neither member variables, there is no class variables. Any access to its threads will not affect the results of another thread, because the state did not share any of the variables between the two threads. So can such a conclusion: class stateless variables must be thread-safe .

Then we will look at a class of state variables. Assume that silence (Chenmo class) each write word line ( write()method), you do a count, so easy to find publishers ask for royalties. We've added a field Chenmo statistical category, the code sample below.

class Chenmo {
    private long count = 0;
    public void write() {
        System.out.println("我寻了半生的春天,你一笑便是了。");
        count++;
    }
}
复制代码

Chenmo class in a single-threaded environment can be accurate statistics on the number of trips, but in a multithreaded environment does not. Because the increment operation count++can be split into three operations: reading the count, the count by 1, the calculation result is assigned to count. Multi-threading, when the timing of these three actions that occur may be confusing, and ultimately figured out the count value will be smaller than the expected value.

PS: specific reason can look back on a " the Java Concurrent Programming (a): gearing up " .

Writing is not easy, you can not ill-treat the silence, right? It. Do something.

A thread count is assumed to modify variables, this time we must prevent the thread or threads C B use this variable, thus ensuring thread B or C using thread count when a state after the A modification thread.

How to prevent it? You can write()add a method on synchronizedthe keyword. Code Example below.

class Chenmo {
    private long count = 0;
    public synchronized void write() {
        System.out.println("我寻了半生的春天,你一笑便是了。");
        count++;
    }
}
复制代码

Keyword synchronizedis one of the most simple synchronization mechanism to ensure that only one thread can execute write(), it ensures that count++a multi-threaded environment is safe.

When writing concurrent applications, we must maintain a correct concept, that is - first of all to ensure that the code to run correctly, and then how to improve code performance.

But we all know, synchronizedthe price is expensive, between multiple threads access write()methods are mutually exclusive, when thread B access must wait for the end of the thread A visit, this does not reflect the core values of multi-threading.

java.util.concurrent.atomic.AtomicIntegerInteger class is to provide a atomic operation, it provides a subtraction operation thread safe. So we can modify Chenmo class code examples below.

class Chenmo {
    private AtomicInteger count = new AtomicInteger(0);
    public void write() {
        System.out.println("我寻了半生的春天,你一笑便是了。");
        count.incrementAndGet();
    }
}
复制代码

write()The method is no longer necessary synchronizedkeywords to keep pace, so they no longer need to be mutually exclusive ways to invoke the method among multiple threads, you can improve the efficiency of statistics to some extent.

One day, in the form of royalties publishing statistics has changed, not only to count the number of lines, but also to count the words, so Chenmo need to add a class member variables. Code Example below.

class Chenmo {
    private AtomicInteger lineCount = new AtomicInteger(0);
    private AtomicInteger wordCount = new AtomicInteger(0);
    public void write() {
        String words = "我这一辈子,走过许多地方的路,行过许多地方的桥,看过许多次的云,喝过许多种类的酒,却只爱过一个正当年龄的人。";
        System.out.println(words);
        lineCount.incrementAndGet();
        wordCount.addAndGet(words.length());
    }
}
复制代码

Do you think this code is thread safe?

The result is obvious, this code is not thread safe. Because lineCount and wordCount are two variables, although their respective thread-safe, but when the thread A is lineCount plus 1, B is not able to guarantee thread after thread A complete implementation of the statistics wordCount start lineCount plus 1.

what can we do about it? The method is also very simple, the following sample code.

class Chenmo {
    private int lineCount = 0;
    private int wordCount = 0;
    public void write() {
        String words = "我这一辈子,走过许多地方的路,行过许多地方的桥,看过许多次的云,喝过许多种类的酒,却只爱过一个正当年龄的人。";
        System.out.println(words);
        
        synchronized (this) {
            lineCount++;
            wordCount++;
        }
    }
}
复制代码

Statistics on the number of lines (lineCount ++) and Count (wordCount ++) code to be locked to ensure that these two lines of code are atomic. In other words, during the thread B statistics, it must wait longer to start after thread A complete statistics.

synchronized (lock) {...}Is a simple Java provides built-in locking mechanism for ensuring atomicity code block. Automatic thread acquires the lock before entering the locked block of code, and the code block when the exit lock release can be ensured by a set of statements executed as an integral unit.


Previous: the Java concurrent programming (a): gearing up

PS: the original is not easy, like to point a praise, this will be my strongest writing power. If you think I write articles to help you, but also quite interesting to look at my public number, "replies the keyword" java ", can receive advanced Java programmers required reading package" Thank you.

Guess you like

Origin juejin.im/post/5d7ee216e51d4561af16ddb2