java multithreaded correlation

1. The state of the thread?

1,New status: new One thread, no more start
2,Running state (ready and running): calling the thread's.start Method
    1)Ready to call start Method, CPU No time slice allocated
    2)Run, invoked start Method, CPU Scheduling in progress
3,Blocking state: when competing synchronized Lock, not got, thread hangs
4,Waiting state: join,wait,(LockSupport)park Method
5,Timeout wait state: Thread.sleep(long),wait(long),join(long),parkNanos(......)
6,Death status: run The method ends, or run Method throws an exception without

2. Thread pool core parameters

Java provides a way to build thread pools based on Executors

Building directly with Executors results in very coarse thread pool control

Thread pool must be built manually

public ThreadPoolExecutor(int corePoolSize,      // Core threads,
                              int maximumPoolSize,  // Maximum Thread Lifetime
                              long keepAliveTime,  // Lifetime,
                              TimeUnit unit,  // Units,
                              BlockingQueue<Runnable> workQueue,  //Task Queue,
                              ThreadFactory threadFactory,  // Thread factory, to set the name of the thread for later debugging
                              RejectedExecutionHandler handler) {}  // Rejection Policy

3. Execution process of thread pool

Submit the task to the thread pool and let the threads in the thread pool execute the task

1. After submitting the task to the thread pool

  • If there are idle core threads, execute directly
  • If there are no idle core threads, try creating core threads to perform tasks

2. If the core thread count configuration has been reached

Drop the task in the queue and wait for the core thread to finish other tasks before executing me

3. Build a maximum number of threads if the task queue is too full to hold the task

4. Execute rejection policy if the maximum thread is already full

4. What is the use of the ctl attribute in the thread pool?

ctl is a property in the thread pool and is essentially a numeric value of type int

High 3 bits describe the state of the thread pool and low 29 bits describe the number of worker threads

When a thread pool executes a task, it needs to determine the state of the thread pool multiple times to determine whether or not the task needs to be executed (in which way)

Low 29 describes the number of existing worker threads in the thread pool

5. The state of the thread pool?

// RUNNING-Thread Pool is working and can handle submitted tasks!!!
    private static final int RUNNING    = -1 << COUNT_BITS;
    // Calls the shuwdown() method of the thread pool, from RUNNING -> SHUTDOWN, and does not receive new tasks, but handles existing tasks within the thread pool, including queues
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    // Call the shuwdownNow() method of the thread pool, from RUNNING -> STOP, do not receive new tasks, interrupt the task being processed, regardless of the work queue task
    private static final int STOP       =  1 << COUNT_BITS;
    // Transition state, from SHUTDOWN and STOP P to TIDYING state
    // SHUTDOWN - Work queue empty, worker thread empty - TIDYING   
    // STOP - Empty worker thread - TIDYING
    private static final int TIDYING    =  2 << COUNT_BITS;
    // When the thread pool reaches TIDYING, terminated is automatically called in the source code, entering TERMINATED state, and the thread pool is cool
    private static final int TERMINATED =  3 << COUNT_BITS;

6. What is a worker thread?

In a Java thread pool, a worker thread is a Worker object

The worker threads in the thread pool are represented by the Worker object

addWorker(Runnable, true/false)
Add one Worker Object to thread pool, Runnable Specific tasks to be performed
true: Core threads added
false: Maximum number of threads added

Worker This is actually an internal class in the thread pool that inherits AQS,Implemented Runnable
private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable{}
The thread pool executes the task, which is actually called Worker In class run Inside Method runWorker Method
Worker inherit AQS The purpose is to add an identity to determine if the current worker thread can be interrupted!

7. Where do worker threads reside?

One stored in the thread pool HashSet in
private final HashSet<Worker> workers = new HashSet<Worker>();

8. Rejection Policy

1: Abort: Throw an exception
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
2: Discard: Throw it away without throwing an exception
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
3: DiscardOldest: Throw away tasks that have been queued the longest and are about to be performed
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);  // Walk ThreadPool execution process again
            }
        }
4: CallerRuns: The caller handles the service, causing a sharp drop in caller performance.
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }

9. How to do extra processing before and after thread pool execution

try {
    // Pre-Enhancement
    beforeExecute(wt, task);
    try {
        // Execute Tasks
        task.run();
    } catch (Throwable x) {
        thrown = x; throw new Error(x);
    } finally {
        // Post Enhancement
        afterExecute(task, thrown);
    }
}

protected void beforeExecute(Thread t, Runnable r) { }

protected void afterExecute(Runnable r, Throwable t) { }

10. How to Reasonably Allocate Thread Pool Size

When allocating thread pool capacity, you must decide based on your business type
CPU Dense, IO Dense, Mixed
CPU Dense: More CPU I'm calculating, I've been working
IO Dense: More time threads are waiting for a response
 Mixed: Everything!
1,CPU Dense: less threads, recommended: CPU Number of Kernels+1
2,IO Dense: more threads, recommended: general CPU Number of Kernels * 2,(Thread Wait Time and Threads CPU Time Ratio + 1) * CPU Number
3,Mixed: can CPU Dense and IO Dense operations can be divided into two thread pools to execute!

11. How to ensure thread security if critical (shared) resources exist

1,Mutex:
    synchronized,Lock(ReentrantLock,ReadWriteLock)
2,Non-blocking lock:
    CAS(Really unlocked, bottom lock cmpexchg Locked, Java Layer unlocked)
3,No locks are used:
    ThreadLocal,Use where appropriate volatile Yes!
    ThreadLocal: Let multiple threads share resources copy Locally, there is no problem with multithreaded operation sharing resources
    volatile: As long as it doesn't include concurrent operations on shared data, it's basically OK.

12. What exactly is ThreadLocal?

ThreadLocal is essentially a Map.
ThreadLocal binds a data to a local thread.

Thirteen. ThreadLocal memory leak?

Four References in Java

Strong reference: OOM is also not cleared

Soft Reference: Out of Memory Cleanup

Weak references: clear as long as GC

Virtual References: If you can't get a reference, it's cool to build it~~

To solve this problem, remove after using TheadLocal

14. volatile

Visibility and prohibition of instruction rearrangement do not guarantee atomicity!

Why does the CPU reorder instructions?

CPU rearranges instructions to improve efficiency while guaranteeing happens-before

In order to prohibit instruction rearrangement, JVM virtual machine proposed specification, memory barrier

  • LoadLoad
  • StoreLoad
  • LoadStore
  • StroeStore

The hotSpot virtual machine is simple to implement by appending a lock between two instructions to specify the effect of implementing volatile

Lock when multithreaded processing shared data at the CPU level.

The lock directive synchronizes data operations in CPU memory to main memory.

15. Pseudo-Sharing (Cache Row Sharing)

CPU is divided into L1, L2, L3 memory, CPU internal memory, which is much faster than looking for data in main memory!

General 64 CPU s have cached rows inside to store data, one of which is 64byte

The usual way to do this is to fill the entire cache row with data from one business.

long l = real data.

long l1,l2,l3,l4,l5,l6,l7;

In JDK1. In 8, the @Contended annotation is usually used

16. CAS

compare And Swap

Problems with CAS:

ABA Problem: Append Version Number Solve

If too many failures take up CPU resources: different scenarios have different solutions

synchronized: The solution is to use an adaptive spin lock and suspend the thread if there are too many spins

LongAdder: When self-increasing, if failed, add failed information to Cell[]

Only one data can be secured: you cannot lock a piece of code like synchronized, ReentrantLock implements the effect of locking based on CAS.

synchronized-ReentrantLock: Watch a video of Teacher Ma and Teacher Huang with systematic explanations

17. ConcurrenthashMap

Just JDK1.8...

ConcurrenthashMap attempts to insert into the array as a CAS when there is no Hash conflict

If there is a Hash conflict, the current array index position is locked back and suspended under the chain table as synchronized

If the length of the array reaches 0.75 of the initial length, double the length of the array and never avoid the inefficiency of queries caused by too long chains

18. How can Concurrent HashMap ensure security during concurrent expansion?

When calculating the hash value of the key in Node, the normal hash value is deliberately defined as a positive number

Negative numbers have a special meaning, if the hash value is -1, it means the current node is expanding

ConcurrenthashMap expands the data table in the old array each time. Size - 1 ~ table. Size - 16 Index position moves before migrating data from other index locations. If a thread inserts data and finds that it is expanding, look for index locations that have not been migrated to help the thread that initially expanded expand.

Initial expansion A:31~16

Thread B inserts data, finds expansion in progress, helps you migrate data, 15~0 index locations

Each migrated data is identified as having been expanded, with a Forwarding Node node placed on it to indicate that the expansion is complete, and then expanded without applying ConcurrentHashMap traversal, queries, and additions (found extensions, will help ~)

19. When a thread expands, it uses sizeCtl to record the number of threads that are expanding now. Why does one thread expand with a low-bit value of 2 and two threads expand with 2?

If sizeCtl is -1, ConcurrentHashMap is initializing and -N is expanding

So you have to identify a thread that is expanding as -2, -2 represents a thread that is expanding

-3 represents two thread extensions.

20. AQS

What is AQS?

AQS is a concurrent base class under JUC package, many of which are implemented based on AQS, such as common ones
ReentrantLock/Semaphore/CountDownLatch/Thread Pool.

AQS structure?

CLH (two-way queue) +state (variable of type int)

Operation state based on bidirectional queues and CAS implements common concurrent content under each JUC

Fair Lock: AQS queues with Node, queue directly without competing for lock resources

Unfair Lock: Nothing, come up and compete directly for lock resources, then go up the routine

This article is published by blog OpenWrite Release!

Tags: Java

Posted by hotdog on Fri, 13 May 2022 20:36:27 +0300