Concurrent programming (multi-threading, JMM, visibility, ordering, atomicity, volatile keyword, lock, JUC)

Review the basic content of threads

Program: a static program written in a certain language to achieve a specific function and installed on the hard disk

Process: A running program, which is the unit by which the operating system allocates memory space.

Thread: The thread is the smallest execution unit in the process and the CPU scheduling unit. The thread depends on the process.

Create thread

1. Inherit the Thread class and override run()

2. The class implements the Runable interface and overrides run()

Create an object of Thread class and assign tasks to it

3. The class implements the Callable interface, overrides call() to have a return value, and can throw exceptions

Create an object of Thread class and assign tasks to it

Common methods

run() call() start()

set name set priority

Thread status start() ready status

​ join() sleep() blocking state

​ yield() The thread gives up the running status and actively gives up ----> ready status
stop() forcibly interrupts the thread (this method is an invalid and expired method)
interrupt() interrupts the thread

Insert image description here

Multithreading

Java is one of the first languages ​​to support multi-threaded development.

Java has supported multithreading from the beginning

ability. Since most of today's CPUs are multi-core processors, they can execute multiple threads at the same time.

Advantages of multithreading

Multi-threading technology makes the program more responsive and can be active while doing other work.

Status, program performance is improved.

The essence of performance improvement is to extract the residual value of hardware (hardware utilization).

Multithreading problem

What are the problems caused by multi-threading?

Security (accessing shared variables), performance (cpu switching overhead, etc.)

java concurrent programming

Concurrency and Parallelism

[External link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-o0nJZR6x-1642328944308) (C:\Users\Cloud\AppData\Roaming\Typora\typora-user-images\ 1642326319274.png)]

Java Memory Model (JMM)

Note that JMM is a java memory model, not a jvm model.

When Java multi-threading is working, it first reads the data in the main memory into the thread's working memory (cache), then operates the data in the working memory, and writes the data back to the main memory after the operation is completed.


Creating a visibility issue?

The data operated in thread A cannot be seen in thread B.
Insert image description here

The operating system may rearrange the order of execution of instructions.

Causes ordering problems
Insert image description here

Thread switching comes with atomicity (non-split) issues

i=1; i=1;

i++ -->i=i+1 i++ 2

2

++ is divided into calculation first and then assignment. The ++ operation is not an atomic operation, and the CPU may execute it in two steps.
Insert image description here

Core issues of concurrent programming

Core issues of concurrent programming – visibility, atomicity, orderliness

Thread local cache, causing visibility issues

Compilation optimization and rearrangement of instructions cause ordering problems

Thread switching execution will cause atomicity problems

How to solve the problem?

volatile keyword

Shared variables modified by volatile: 1. After operation in one thread, it can be guaranteed to be immediately visible in another thread. 2. Reordering of optimization instructions is prohibited. 3. The atomicity of variable operations cannot be guaranteed.

i++ is not an atomic operation. How to solve the problem of locking?

How to ensure atomicity

"Only one thread is executing at the same time" we call it mutual exclusion. If we can ensure that modifications to shared variables are mutually exclusive, then atomicity can be guaranteed.

Lock

Lock ReentrantLock

synchronized can also guarantee visibility and ordering

Atomic class

java.util.concurrent包

AtomicInteger implements atomic operations through volatile+CAS

getAndIncrement(); is safe instead of i++

CAS can be understood as a spin thought

CAS (Compare-And-Swap) comparison and exchange is suitable for low concurrency situations

CAS is an implementation method of optimistic locking. It adopts the idea of ​​spin and is a lightweight locking mechanism.

Optimistic locking refers to a way that can be solved without locking (that is, there is no lock)

Spin lock (polling) keeps checking in a loop

CAS contains three operands:

①Memory value V

②Estimated value A (the value read again from the memory during comparison)

③Update value B (updated value)

If and only if the expected value A==V, set the memory value V=B, otherwise do nothing.

This approach is more efficient than locking. When the judgment is unsuccessful and the value cannot be updated, it will not block and continue to obtain the CPU.

Right to execute, continue to judge and execute

This approach will not cause thread blocking because there is no lock

shortcoming:

In high concurrency situations, the spin method is used to continuously loop, which has a high CPU usage.

ABA problems may arise. You can add a version number to a class to distinguish whether the value has been changed.

ABA questions

ABA problem, that is, a thread changes the memory value from A to B, and then from B to A. when another

When the thread uses the expected value to judge, the expected value is the same as the memory value, mistakenly thinking that the variable has not been modified.

caused problems.

The main way to solve ABA problems is to avoid ABA problems by using methods like adding version numbers.

For example, the original memory value is (A, 1), and the thread changes (A, 1) to (B, 2), and then (B, 2)

Modify to (A, 3). At this point another thread uses the expected value (A, 1) with the memory value (A, 3)

For comparison, you only need to compare version numbers 1 and 3 to find that the data in the memory has been updated.

JUC class

hashMap is thread-unsafe and cannot be operated concurrently

HashTable is thread-safe and has synchronized modification. Adding the lock directly to put() is inefficient. It is equivalent to locking the entire hash table. It can be used in low concurrency situations. Exclusive lock

ConcurrentHashMap

ConcurrentHashMap is thread-safe. It adopts the lock segmentation mechanism and does not lock the entire hash table. However, segmented locks are not used after jdk8 (create a lock flag object for each position), and it is implemented using CAS idea + synchronized

When inserting, check whether the position corresponding to the hash table is the first node. If so, use the CAS mechanism (loop detection) to insert data into the first position.

If this position already has a value, then the first Node object is used as the lock flag to lock, using the synchronized implementation.

public class HashMapDemo {
    
    

    /*
       HashMap是线程不安全的,不能并发操作的
       ConcurrentModificationException  并发修改异常   遍历集合,并删除集合中的数据

       Hashtable 是线程安全的 public synchronized V put(K key, V value)-->独占锁
            锁直接加到了put方法上,锁粒度比较大,效率比较低
            用在低并发情况下可以

       Map<String,Integer> map = Collections.synchronizedMap(new HashMap<>());
       ConcurrentHashMap
     */
    public static void main(String[] args) {
    
    

        ConcurrentHashMap<String,Integer> map = new ConcurrentHashMap<>();
        //模拟多个线程对其操作
        for (int i = 0; i < 20; i++) {
    
    
                 new Thread(
                     ()->{
    
    
                       map.put(Thread.currentThread().getName(), new Random().nextInt());
                         System.out.println(map);
                     }
                 ).start();
        }

    }
}

Guess you like

Origin blog.csdn.net/crraxx/article/details/122526635