This section begins to explore the principle of concurrency, understanding the principle of concurrency is the subsequent use of JDK concurrency tools and write their own concurrent scenario code knowledge reserve. Let’s consider two questions first

  1. What scenarios need to consider concurrency?
  2. Why not consider concurrency for local variables without sharing?
  3. What does the emphasis on atomicity, order, and visibility in concurrency mean?
  4. With distributed locks, is Java’s own concurrency still necessary?

1. Make small talk

The following questions are left for readers to ponder in this section

1.1 When can concurrency be considered?

Concurrency is to solve the problem of sharing data, such as static variables, database resources, redis data, so concurrency needs to be considered when sharing data across multiple threads.

1.2 How many threads does my program have?

1.3 Does my method have concurrency problems?

1.4 Sharing – The bane of concurrency problems

2. Concurrency features

2.1 atomic

That is, an operation is a whole, and there is no partial execution. Example: the i++ operation is not atomic. You can use the incrementAndGet() method of AtomicInteger or the CAS operation of the Unsafe class.

2.2 order

For performance purposes, the JVM and memory reorder instructions.

public class Singleton {
  private static Singleton instance;
  public static Singleton getInstance(a){
    if (instance == null) {
      synchronized(Singleton.class) {
        if (instance == null)
          instance = newSingleton(); }}returninstance; }}Copy the code

To prevent instruction reordering, use synchronized or lock mechanisms

public class Singleton {
  private static Singleton instance;
  public synchronized static Singleton getInstance(a){
    if (instance == null) {
      synchronized(Singleton.class) {
        if (instance == null)
          instance = newSingleton(); }}returninstance; }}Copy the code

2.3 the visibility

Visibility refers to the ability of variables modified in one thread to be immediately visible to other threads. Visibility problems in multi-threaded environments are mainly due to the presence of working memory, which is divided into two parts:

Each thread uses working memory and only reads data from main memory when working memory fails.

// Use the following code: Flag was changed to true, but was not immediately known in the main thread, Public class Test {public static void main(String[] args) {ThreadDemo td = new ThreadDemo(); new Thread(td).start(); while (true) { if (td.isFlag()) { System.out.println("---end break---"); break; } } } } class ThreadDemo implements Runnable { private boolean flag =false; @Override public void run() { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } flag = true; System.out.println("flag=" + flag); } public boolean isFlag() { return flag; }}Copy the code

To address visibility issues, you can use the volatile keyword or invalidate working memory. When does the in-work existence expire?

  1. When the CPU is idle (IO operation, system.out.xxx operation)
  2. When a lock is released in a thread (for example, when a wait method is called)
  3. Thread switching (sleep() method, etc.)