This is the seventh day of my participation in the August More text Challenge. For details, see:August is more challenging
Processes and Threads
- Process: The smallest unit of resource allocation in a system. Each process has its own code and data space — the process’s context
- Context switch: The action of a CPU to switch from one process to another
- 1. A countervaling unit of CPU scheduling that is part of a process and can only be created by a process (divided into user threads and daemon threads).
- Each thread shares the process’s data space, and each thread has its own stack and program counter
Concurrency and parallelism
- parallelRunning multiple tasks simultaneously on multiple computers at the same time (similar: ten children are divided into two groups, one group is playing with a toy car, the other group is playing with a teddy bear, these two groups are
parallel
Play) - Concurrent: Perform multiple tasks at the same time (similar: 10 children grab a stationery to play, each play for a while)
Public class MyThread extends Thread{@override public void run(){for(int I = 0; i < 1000; i++){ try{ Thread.sleep(10L); }catch(InterruptedException e){ e.printStackTrace(); } } } public static void main(String[] args) { Thread t = new MyThread(); t.start(); }}Copy the code
tips:
- The code in the run() method doesn’t necessarily start executing immediately after the start() method is called; the start() method simply makes the county available
The ready state
When to run is determined by the operating system
The difference between wait and sleep
- The wait() method must be used within a synchronized block or method
- Blocks caused by wait() can be called from the synchronized scope on the same object lock
notify()/notifyAll()
To wake up; Sleep (), on the other hand, cannot be awakened; it can only be periodically awakened or interrupted by the interrupt() method
The difference between sleep and yield
- call
sleep()
Method post-transferThe blocking state
And automatically wake up after a period of sleepThe ready state
- call
yield()
Method, the current thread entersThe ready state
- The sleep() method gives threads a chance to run regardless of their priority, while yield() gives only those threads of the same or higher priority a chance to run
The thread pool
Frequently asked interview questions: How do I create a thread pool
- Thread pools are not allowed according to the Ali Development Manual
Executors
Create, but passThreadPoolExecutor
Is created by - Disadvantages of the thread pool object returned by Executors
1.FixedThreadPool and SingleThreadPool allow queue lengths of integer.max_value, which may result in a large number of requests. CachedThreadPool and ScheduleThreadPool allow request queues of Integer.MAX_VALUE, which may accumulate a large number of requests, resulting in OOMCopy the code
Frequently asked parameters:
Int corePoolSize Number of core threads int maximumPoolSize Maximum number of threads keepAliveTime Maximum idle time of a thread
Ways to Ensure thread synchronization (simple list)
The CAS operation
- How it works: Before updating a variable, check that the current value of the variable matches the expected value. If it does, replace the old value with the new value. Otherwise, loop retry (spin) until success
- Simple implementation of a counter with CAS (including thread safe/unsafe)
private AtomicInteger atomicI = new AtomicInteger(0); private int i = 0; public static void main(String[] args) { final Counter cas = new Counter(); List<Thread> ts = new ArrayList<Thread>(600); long start = System.currentTimeMillis(); for (int j = 0; j < 100a; j++) { Thread t = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10000; i++) { cas.count(); cas.safeCount(); }}}); ts.add(t); } for (Thread t : ts) { t.start(); } for (Thread t: ts) {try {t.jin (); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(cas.i); System.out.println(cas.atomicI.get()); System.out.println(System.currentTimeMillis() - start); */ private void safeCount() {for (;;)) { int i = atomicI.get(); boolean suc = atomicI.compareAndSet(i, ++i); if (suc) { break; } /** * private void count() {i++; }}Copy the code
Three major problems of CAS
1. The problem of ABA.
- Because CAS needs to check whether the value has changed when operating on it, and update it if it has not changed.
- But if A value is A, then B, and then A, then the CAS check will find that its value has not changed,
- But the reality has changed. The solution to the ABA problem is to use version numbers. Append the version number to the variable,
Add the version number by 1 each time the variable is updated, so that A→B→A becomes 1A→2B→3A
. - Starting with Java 1.5, a class is provided in the JDK’s Atomic package
AtomicStampedReference
To solve the ABA problem. - The compareAndSet method of this class first checks to see if the current reference equals the expected reference and if the current flag equals the expected flag.
- If all are equal, the reference and the value of the flag are set atomically to the given update value.
2. Long cycle time and high overhead.
- If spinning CAS is not successful for a long time, it will bring a very large execution overhead to the CPU. If the JVM can support what the processor provides
pause
Instructions, - There will be some improvement in efficiency. The pause directive does two things:
First, it can delay pipeline execution instructions (DE-pipeline), so that the CPU will not consume too much execution resources, the delay time depends on the specific implementation version, in some processors delay time is zero;
Second, it prevents CPU Pipeline Flush from exiting a loop due to Memory Order Violation
Improves THE CPU execution efficiency. 3. Only one atomic operation can be guaranteed for a shared variable.
- When performing operations on a shared variable, we can use a cyclic CAS to guarantee atomic operations,
- However, when operating on multiple shared variables, the cyclic CAS cannot guarantee the atomicity of the operation, and locks can be used. Another trick is to combine multiple shared variables into a single shared variable.
- For example, there are two shared variables
I =2, j=a, combine ij=2a
And then use CAS to manipulate ij. Starting with Java 1.5, - The JDK provides the AtomicReference class to ensure atomicity between reference objects, so that multiple variables can be placed in a single object to perform CAS operations.
Lock the spin Lock
java.util.concurrent.locks
The lock is provided in the packageLock
Interface and its implementation classReentrantLock
- in
ReentrantLock
In the calllock()
Method to obtain the lock; callunlock()
Method to release the lock. ReentrantLock
Relies on the Java synchronizer frameworkAbstractQueuedSynchronizer
(AQS for this article). AQS uses an integervolatile
Variable (named state) to maintain the synchronization state
The source code
CountDownLatch counter
- Multiple threads call their shared counters (
CountDownLatch
Object)countDown()
Method to subtract 1 from the counter - Can be achieved by
CountDownLatch
The object’sawait
Method to block the current thread until the counter value is 0;
1.
- When we call CountDownLatch
countDown()
Method, N will be reduced by one, CountDownLatchawait()
Method blocks the current thread, - Until N goes to zero. Due to the
countDown
The method can be used anywhere, so it could be N points, it could be N threads, it could be N steps in a thread. - When using multiple threads, you simply pass a reference to the CountDownLatch to the thread.
2.
- If one of the parsing sheets is slow, we can’t keep the main thread waiting, so we can use another thread with a specified time
await()
methods Await (long time, TimeUnit unit)
This method waits a certain amount of time before it no longer blocks the current thread.join
There are similar methods.
CyclicBarrier fence
- CyclicBarrier is a reusable thread blocker that is called
await()
Method forms a “fence” in the code and executes until the “await() method” blocks until the specified number of threads have reached the “fence”.