Hello everyone, I am xiao CAI, a desire to do CAI Not CAI xiao CAI in the Internet industry. Soft but just, soft praise, white piao just! Ghost ~ remember to give me a three – even oh!

This article mainly introduces the JUC and high concurrency in Java, if necessary, can refer to the Sunday for help, do not forget to praise

A Volatile,

Volatile is a lightweight synchronization mechanism provided by the Java Virtual machine

1) Ensure visibility

Thread work in JMM model: each thread’s operation on the shared variable X in main memory is copied by each thread to its own working memory operation and then associated to main memory.

Problem: If thread A changes the value of shared variable X and does not write back to main memory, it is another thread B that operates on A shared variable X in memory, but the shared variable in thread A’s working memory is not visible to thread B. This phenomenon of working memory and main memory latency creates visibility problems.

Volatile: When multiple threads access the same variable, if one thread changes the value of the variable, the other threads can see the change immediately

2) Atomicity is not guaranteed

Atomicity: Indivisibility and integrity, that is, when a thread is doing a specific business, the middle cannot be added or divided, but the whole thread must be complete, and either succeeds or fails at the same time

Solutions:

  • Join the synchronized

  • Use AtomicInteger under JUC

3) Forbid instruction rearrangement

Instruction rearrangement: Threads are executed alternately in a multithreaded environment. Due to the rearrangement of compiler optimizations, the consistency of variables used in the two threads is uncertain and the results unpredictable.

Instruction reordering process: source code -> editor optimized reordering -> instruction parallel reordering -> memory system reordering -> instructions finally executed

Memory barrier function:

  • Ensure the order in which certain operations are performed
  • Ensure memory visibility for certain variables (use this feature for volatile memory visibility)

Second, the CAS

1) What is CAS

  • Full name of CAS: compare-and-set. CAS is a CPU parallel language

  • Its function is to determine whether a value at a location in memory is the expected value, and if so, update it to the new value. This process is atomic.

  • Calling the CAS method in the UnSafe class, the JVM will implement the CAS assembly instruction for me, which is a completely hardware-dependent function that implements atomic operations. Again, since CAS is a system source language, The source language belongs to the category used by the operating system and is a process composed of several instructions to complete a certain function. In addition, the execution of the source language must be continuous and no interruption is allowed in the execution process. In other words, CAS is an atomic instruction and will not cause the so-called data inconsistency problem

public class CASDemo{

    public static void main(String[] args) {

        AtomicInteger atomicInteger = new AtomicInteger();

        System.out.println(atomicInteger.compareAndSet(0.5));       //true

        System.out.println(atomicInteger.compareAndSet(0.2));       //false

        System.out.println(atomicInteger);                          / / 5

    }

}

Copy the code

2) CAS principle

    public final int getAndIncrement(a) {

        return unsafe.getAndAddInt(this, valueOffset, 1); // What is unsafe

    }

Copy the code

3) What is UnSafe

  • UnSafe is the core CAS class. Since Java methods cannot access the underlying layer directly, they need to access it through native methods. UnSafe is equivalent to a background class that can directly manipulate memory data. The UnSafe class is in the Sun.misc package. Internal methods can manipulate memory as directly as Pointers to C, because CAS operations in Java rely on the UnSafe class’s methods

  • The variable ValueOffset, which is the address offset in memory, is also used to retrieve data.

  • The value variable is volatile, ensuring visibility across multiple threads.

4) DISADVANTAGES of CAS

  1. Cycle time is expensive
  1. Only one shared variable can be atomized. We can loop CAS to ensure atomic operation on one shared variable. However, when multiple shared variables are operated on, the loop CAS cannot guarantee atomic operation.
  2. ABA problems

5) ABA problems

What is the ABA problem: Data changes over a time difference. From memory such as A thread AA take A, this time another thread BB is removed from memory. A, this time A value of X, then thread BB will A to change the value of Y, later again will be to change the value of X, A thread AA back at this time for the CAS operation found in memory of A value is still the X, so the thread AA operation is successful. But just because the CAS operation on thread AA is successful doesn’t mean the process is fine

Atomic reference:

Solution: (Timestamp atom reference: AtomicStampedReference)

Third, the collection class is not safe

1) Fault symptoms

In Java. Util. ConcurrentModificationException anomalies

2) Causes

Concurrent scrambling caused by modification

public static void main(String[] args) {

    List<String> stringList = new ArrayList<>();

    for (int i = 0; i < 30; i++) {

        new Thread(()->{

            stringList.add(UUID.randomUUID().toString().substring(0.8));

            System.out.println(stringList);

        },"Thread"+i).start();

    }

}

Copy the code

3) Solutions

  • Vector: Thread-safe
  • Collections.synchronizedList(new ArrayList<>())
  • new CopyOnWriteArrayList<>()
  • The List thread:new CopyOnWriteArrayList&lt; &gt; (a);
  • Set the thread:new CopyOnWriteArraySet&lt; &gt; (a);
  • Set the thread:ConcurrentHashMap();

Four, lock

1) Fair lock/unfair lock

Definition:

Fair lock: refers to multiple threads for lock in order to get the lock, is similar to line up, FIFO rule of fair lock: refers to the order is not in a multithreaded access to lock in the order application locks, may after the application thread than apply for the thread priority to lock, in the case of high concurrency, may cause the priority inversion or hunger.

The difference between the two:

ReentrantLock can be created by specifying the Boolean type of the function to get a fair or unfair lock. The default is unfair lock

Fair lock: is very fair, in the concurrent environment, each thread in the lock will first check the lock maintenance wait queue, if it is empty, or the current thread is the first waiting queue, hold the lock, otherwise it will join the wait queue, in accordance with the RULES of FIFO from the queue to extract their own. Unfair lock: Unfair lock is rude, first try to possess the lock, if the attempt fails, use a similar way to fair lock.

In the case of Java ReentrantLock, the constructor specifies whether the lock is a fair lock, by defaultNot fair lock, the advantage of unfair lock is that the throughput is higher than that of fair lock. As far as synchronized is concerned, it is an unfair lock.

2) Reentrant lock (recursive lock)

Reentrant lock, also known as recursive lock, specifies that the same thread after the outer function obtains the lock, the inner recursive function can still obtain the lock code, when the same thread obtains the lock in the outer method, the inner method will automatically acquire the lock. That is, a thread can enter any block of code synchronized with a lock it already owns

ReentrantLock and Syschronized are typical examples of reentrant locks

Already, for instance:

Syschronized example:

3) Spin lock

A thread that attempts to acquire a lock does not block immediately. Instead, the thread attempts to acquire the lock in a loop, which has the advantage of reducing the consumption of thread context switching, but has the disadvantage of consuming CPU.

The unsafe in the CAS question above uses spin locks.

public final int getAndAddInt(Object var1, long var2, int var4) {

    int var5;

    do {

        var5 = this.getIntVolatile(var1, var2);

    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

    return var5;

}

Copy the code

Example:

4) Exclusive lock (write)/ shared lock (read)/ mutex

  • Exclusive lock: the lock can only be held by one thread at a time. ReentrantLock and Synchronize are exclusive locks.
  • Shared lock: The lock can be held by multiple threads.

For ReentrantReadWriteLock, its read lock is shared and its write lock is exclusive. Shared locks that read locks ensure concurrency are very efficient. Reading, writing Reading, writing are mutually exclusive.

Example:

5) CountDownLatch

  • Let some threads block until others have finished

  • CountDownLatch has two main methods. When one or more threads call the await method, the calling thread blocks. Other threads call the countDown method and the count decrement by one (the thread does not block when the countDown method is called). The thread blocked by calling the await method is woken up and continues execution.

    Key methods: 1) await() method 2) countDown() method

    Example:

    A classroom has 1 monitor and several students, monitor can not close the door until all the students leave, so how to achieve.

6) CyclicBarrier

  • Cyclicbarriers literally mean barriers that can be used cyclically. All it does is make a group of threads block when they reach a barrier (also known as a synchronization point), the barrier opens until the last thread reaches the barrier, and all threads blocked by the barrier continue to work. Threads enter the barrier through the await() method of the CyclicBarrier.

    Example:

    As above, there are six students in a class and the monitor can’t close the door until all the students have left.

CountDownLatch and CyclicBarrier are actually opposite operations, one is executed by subtracting to zero and the other is executed by adding to the specified value

7) Semaphore

  • The primary user purposes of semaphores are mutually exclusive use of shared resources and control of the number of concurrent resources.
  • Example: parking problem, there are six vehicles, but only three parking problem.

Block the queue

Concept: Blocking queues, divided into “blocking” and “queue”, so-called blocking, in the multi-threaded world, some cases will scrape the thread (i.e., thread blocking), once the condition is met, the suspended thread is automatically woken up first.

Tread 1 adds elements to the blocking queue, and Thread 2 removes elements from the blocking queue

  1. When the blocking queue is empty, fetching elements from the queue will be blocked.
  2. When the blocking queue is full, adding elements from the queue will be blocked.

1) type

  1. ArrayBlockingQueue: ArrayBlockingQueue is a bounded blocking queue based on an array structure that is sorted according to FIFO.
  2. LinkedBlockingQueue: A linked list-based bounded blocking queue (default size Integer.MAX_VALUE) that sorts elements in FIFO (first in, first out) and typically has a higher throughput than ArrayBlockingQueue.
  3. SynchronusQueue: A blocking queue that does not store elements. Each insert operation must wait until another thread calls a remove operation. Otherwise, the insert operation is blocked and throughput is usually higher than LinkedBlockingQueue.
  4. PriorityBlockingQueue: An unbounded blocking queue that supports priority sorting
  5. DelayQueue: delay unbounded blocking queue implemented using priority queues.
  6. LinkedTransferQueue: An unbounded blocking queue consisting of a linked list structure.

Throughput: SynchronusQueue > LinkedBlockingQueue > ArrayBlockingQueue

2) Benefits of use

We don’t have to worry about when we need to block or wake up threads because BlockingQueure does it all for you. Prior to the release of the Concurrent package, in a multi-threaded environment, we had to control these details ourselves, especially with regard to efficiency and thread safety, which caused considerable complexity in our programs

3) Core methods

Method type Throw exceptions Special values blocking timeout
Insert method add(o) offer(o) put(o) offer(o, timeout, timeunit)
Remove method remove(o) poll() take() poll(timeout, timeunit)

| | | check method element () peek () | | is unavailable

  • Throw exception: If the operation cannot take place immediately, an exception is thrown
  • Special value: If the operation does not take place immediately, a special value will be returned, usually true or false
  • Always blocking: If the operation does not proceed immediately, the operation will be blocked
  • Timeout exit: If the operation is not performed immediately, the operation will be blocked for the specified time. If the operation is not performed for the specified time, a special value, usually true or false, will be returned

4) use

  • Producer-consumer model
  • The thread pool
  • Message middleware

Producer-consumer Model — Traditional Version:

Producer-consumer mode — Blocking queue edition:

Thread pools

Concept: The main job of a thread pool is to control the number of running threads, queue tasks in the process, and then start those tasks after the thread is created. If the number of threads exceeds the maximum number, the exceeded threads will queue up and wait for other threads to complete before pulling the task from the queue to execute. Features:

  • Thread the reuse
  • Controls the maximum number of concurrent requests
  • Management of thread

Advantages:

  • Reduce resource consumption by reusing self-created threads to reduce the cost of thread creation and destruction.
  • Improved response time so that when a task arrives, it can be executed immediately without waiting for the thread to be created.
  • Improve the manageability of threads, threads are scarce west court, if unlimited creation, not only will consume system resources, but also reduce the stability of the system, using threads can be unified allocation, tuning and monitoring.

1) Thread creation several methods

1) Inherit Thead

class ThreadDemo extends Thread{

    @Override

    public void run(a) {

        System.out.println("ThreadDemo running...");

    }

    public static void main(String[] args) {

        ThreadDemo threadDemo = new ThreadDemo();

        threadDemo.start();

    }

}

Copy the code

2) Implement Runnable interface

class RunnableDemo{

    public static void main(String[] args) {

        new Thread(new Runnable() {

            @Override

            public void run(a) {

                System.out.println("RunnableDemo running...");

            }

        }).start();

    }

}

Copy the code

3) Implement Callable

public static void main(String[] args) throws ExecutionException, InterruptedException {

        FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {

            @Override

            public Integer call(a) throws Exception {

                return 1;

            }

        });

        new Thread(futureTask).start();

        System.out.println(futureTask.get());

    }

Copy the code

2) Architecture description

Thread pools in Java use the Excutor framework, which uses the Executor, Executors, ExecutorService, and ThreadPoolExecutor classes.

3) Key points

  • Executors.newFixedThreadPool()

    Features:

  1. Create a fixed-length thread pool that controls the maximum number of concurrent threads. The excess threads will wait in the queue.

  2. NewFixedThreadPool creates a thread pool CorePoolSize equal to MaximumPoolSize and uses LinkedBlockingQueue.

    public static ExecutorService newFixedThreadPool(int nThreads) {

          return new ThreadPoolExecutor(nThreads, nThreads, 0.

                  TimeUnit.MICROSECONDS, new LinkedBlockingDeque<Runnable>());

      }

    Copy the code
  • Executors.newSingleThreadExecutor()

    Features:

  1. Create a single threaded thread pool that uses a single worker thread to execute tasks, ensuring that all tasks are executed in the specified order.

  2. NewSingleThreadExecutor sets both corePoolSize and MaximumPoolSize to 1 and uses LinedBlockingQueue.

    public static ExecutorService newSingleThreadExecutor(a) {

        return new ThreadPoolExecutor(1.1.0.

                TimeUnit.MICROSECONDS, new LinkedBlockingDeque<Runnable>());

    }

    Copy the code
  • Executors.newCachedThreadPool()

    Features:

  1. Create a cacheable thread pool with the flexibility to recycle idle threads if the pool length exceeds processing requirements, or create new threads if none are available.

  2. NewCacheThreadPool sets corePoolsize to 0 and MaximumPoolSize to integer. MAX_VALUE, which uses SynchronousQueue, which means that the task is created to run on a thread. If the thread is idle for more than 60 seconds, the thread is destroyed

    public static ExecutorService newCachedThreadPool(a) {

        return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60.

                TimeUnit.SECONDS, new SynchronousQueue<>());

       }

    Copy the code

4) Seven parameters

parameter role
corePoolSize Number of resident core threads in the thread pool
maximumPoolSize The maximum number of concurrent threads in a thread pool must be greater than 1
keepAliveTime The lifetime of redundant idle threads. When the keepAliveTime value is reached, the redundant threads are destroyed until only corePoolSize remains
TimeUnit keepAliveTime
workQueue Blocking the task queue
threadFactory Represents a thread factory that generates worker threads in the thread pool. The user creates a new thread, usually using the default
RejectedExecutionHandler Reject policy, which means how to reject when the thread queue is full and the worker thread is greater than the maximum display size of the thread pool

5) How thread pools work





Example:

Suppose a bank has a total of six Windows (maximumPoolSize), and three Windows (corePoolSize) are opened on weekends. During working hours, three Windows can handle the business, and another one comes at this time, so the three Windows can not handle the business. New customers are sent to the workQueue and then to the workQueue if more come in. But if the waiting area is also full. The business manager (threadFactory) notifies the remaining Windows to open for business processing, but if all six Windows are full and the waiting area is too empty. At this point, the bank needs to consider the RejectedExecutionHandler method to reject the customer. Time went by slowly, the clients who handled the business almost left, only 3 clients were still handling the business. At this time, they began to wait for a certain time (keepAliveTime). If there is no customer to deal with the business when the time comes, these three new Windows can be closed and go back to rest. But the original three Windows (corePoolSize) will remain open.

6) Rejection strategy

When the wait queue is full and no more tasks can be filled, and the number of new tasks reaches maximumPoolSize, we need to adopt the rejection policy mechanism to handle the problem properly. The following built-in rejection policies implement the RejectExecutionHandler interface

  • AbortPolicy (default):

Throw RejectedException to prevent the system from running properly.

  • CallerRunPolicy:

The “caller runs” is a mediation mechanism that neither abandons tasks nor throws exceptions. The thread calls the Execute itself that runs the task. This strategy provides a simple feedback control mechanism that slows down the delivery of new tasks.

  • DiscardOldestPolicy:

Discard the longest waiting task in the queue, and then queue the current task to try again (if it fails again, repeat the process).

  • DiscardPolicy:

Discarding the task without handling or throwing an exception is the best rejection strategy if the task is allowed to be lost.

7) Why not use JDK to create thread pool methods

Thread resources must be provided through the thread pool. Thread creation is not allowed to be displayed in the application. Note: The benefit of using a thread pool is to reduce the time spent creating and destroying threads and the overhead of system resources, solving the problem of insufficient resources. If you don’t use thread pools, you can run out of memory or “overswitch” by creating a large number of similar threads. 【 Mandatory 】 Thread pools cannot be created by Executors. Use ThreadPoolExecutor to clear the running rules of the thread pool and avoid resource depletion.

  1. FixedThreadPoolSingleThreadPoolThe allowed queue length is integer. MAX_VALUE, which may accumulate a large number of requests and result in OOM.
  2. CacheThreadPoolScheduledThreadPool: The number of threads allowed to be created is integer. MAX_VALUE, which may create a large number of threads, resulting in OOM.

Example:

8) Properly configure thread pools

CPU intensive:

  • Check the number of CPU cores:Runtime.getRuntime().availableProcessors()
  • Cpu-intensive means that the task requires a lot of computation without blocking, and the CPU needs to run at full speed all the time.
  • Cpu-intensive tasks can only be accelerated on true multicore cpus (through multithreading)
  • Formula: Number of CPU cores +1 thread pool

IO intensive:

  • Since IO intensive task threads are not always executing tasks, configure as many threads as possible, such as CPU cores x 2
  • IO intensive: indicates that the task requires a lot of I/OS, that is, a lot of blocking. So running IO intensive tasks on a single thread can waste a lot of CPU power on waiting, so using multiple threads can greatly speed up the program, even on a single-core CPU, and this speed mainly takes advantage of wasted blocking time.
  • Formula for configuring threads: Number of CPU cores / 1- Blocking coefficient (0.8-0.9) => For example, for an 8-core CPU, 8/1-0.9 = 80 threads

Deadlock coding and location analysis

1) What is a deadlock

Deadlock refers to two or more than two processes in the process of execution, due to competition for resources of the phenomenon of a kind of wait for each other, if there is no interference of external force so they will not be able to push down, if the system resource is enough, the process of resource requests can be satisfied, the possibility of deadlocks occur is very low, otherwise it will due to competition for limited resources into a deadlock.

2) Causes

  • Insufficient resource system
  • Processes are running in an inappropriate order
  • Misallocation of resources

Example:

The printed result is deadlocked:

3) Solutions

  • jpsCommand to locate the process ID
  • jstackFind the deadlock to view
They’re all bad guys

Today you work harder, tomorrow you will be able to say less words!

I am xiao CAI, a man who studies with you. 💋