The source of atomicity problems is thread switching. If thread switching is disabled, atomicity problems will not occur, but thread switching depends on CPU interruption, which is not possible in multi-core environment. As a typical example, on a 32-bit CPU, a write operation is performed on the long line. The long variable is 64 bits. On a 32-bit CPU, the write operation is divided into two parts: high 32 bits and low 32 bits.

In the multi-core scenario, there may be two threads executing at the same time, one on CPU-1 and the other on CPU-2. In this case, if CPU interruption is disabled, only the continuous execution of the THREADS on the CPU can be ensured, but only one thread can execute at the same time. If the two threads write the high 32 bits of the long variable at the same time, The results will exceed expectations.

There is one very important condition: only one thread is executing at a time, called “mutex.” The atomicity problem can be solved if operations on shared variables are guaranteed to be mutually exclusive.

A simple model of a lock

A critical region

Improved model of locks

In a multithreaded world, locks do not exist in isolation, but are usually used to protect a resource

The synchronized keyword

Java provides the synchronized keyword, which modifies method blocks as well as methods:

class X {
    // Decorates non-static methods
    synchronized void foo(a) {
        / / critical region
    }
    
    // Decorate static methods
    synchronized static void bar(a) {
        / / critical region
    }
    
    // Decorates the code block
    Object obj = new Object();
    void baz(a) {
        synchronized(boj) {
            / / critical region}}}Copy the code

Synchronized implicitly contains lock() and unlock(). Manual unlock is not required.

For static methods, the Class object of the current Class is locked. For non-static methods, the current object instance is locked.