java high concurrency multithreading learning of JUC
1. Definition of JUC
Source code + official documents
java. Three interfaces and tool classes under util Toolkit
**Business: * * common Thread code: Thread
**Runnable interface: * * no return value, lower efficiency than Callable
2. Threads and processes
Threads and processes are summarized in one sentence
**Process: * * a program, such as QQ exe,Music. Collection of exe programs
- A process can often contain multiple threads, at least one!
- java has two threads by default: main and GC
**Thread: * * for example, a Typora process is currently started, in which a specific thread is responsible for single operations such as typing, saving and deleting
- java implements threads: Thread, Runnable, Callable.
Can Java programs really start threads? Look at the source code!
/** * Causes this thread to begin execution; the Java Virtual Machine * calls the <code>run</code> method of this thread. * <p> * The result is that two threads are running concurrently: the * current thread (which returns from the call to the * <code>start</code> method) and the other thread (which executes its * <code>run</code> method). * <p> * It is never legal to start a thread more than once. * In particular, a thread may not be restarted once it has completed * execution. * * @exception IllegalThreadStateException if the thread was already * started. * @see #run() * @see #stop() */ public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ if (threadStatus != 0) throw new IllegalThreadStateException(); /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */ group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } } private native void start0();
- Note that the start0() method is modified with the native keyword. This method is a local method, not completed by java programs, but operated by other C/C + + programs. Because java programs must be executed in the JVM environment and cannot directly operate computer hardware, the creation of threads is not completed by java programs in essence!
The difference between concurrency and parallelism
Concurrent programming: concurrent, parallel
Concurrency: (multiple threads operate on the same resource)
- One CPU core simulates multiple threads to achieve concurrency through fast alternate execution
Parallel: (multiple threads execute simultaneously)
- The CPU is multi-core, and multiple threads can be executed at the same time; Thread pool.
The essence of concurrent programming: make full use of CPU resources!
Several states of threads
/** * A thread state. A thread can be in one of the following states: * <ul> * <li>{@link #NEW}<br> * A thread that has not yet started is in this state. * </li> * <li>{@link #RUNNABLE}<br> * A thread executing in the Java virtual machine is in this state. * </li> * <li>{@link #BLOCKED}<br> * A thread that is blocked waiting for a monitor lock * is in this state. * </li> * <li>{@link #WAITING}<br> * A thread that is waiting indefinitely for another thread to * perform a particular action is in this state. * </li> * <li>{@link #TIMED_WAITING}<br> * A thread that is waiting for another thread to perform an action * for up to a specified waiting time is in this state. * </li> * <li>{@link #TERMINATED}<br> * A thread that has exited is in this state. * </li> * </ul> * * <p> * A thread can be in only one state at a given point in time. * These states are virtual machine states which do not reflect * any operating system thread states. * * @since 1.5 * @see #getState */ public enum State { // establish NEW, // function RUNNABLE, // block BLOCKED, // Wait - wait all the time WAITING, // Timeout wait - limit time (out of date) TIMED_WAITING, // Destroy TERMINATED; }
The difference between wait/sleep
1. From different classes
Wait() = > > > object class sleep() = = > > > thread class
2. Release of lock
wait will release the lock. sleep if someone falls asleep and forgets to release the lock!
3. The scope of use is different
Wait = = > > > sync code block sleep = = > > > anywhere
4. Exception capture
Both require interrupt exception capture!
3. Lock lock (key)
Traditional synchronized lock
Lock lock
Fair lock: very fair, first come, first served
Unfair lock: very unfair: you can jump the queue (default)
The difference between Synchronized Lock and Lock lock
1. Synchronized is a built-in Java keyword, and Lock is a java interface;
2. Synchronized cannot judge the status of obtaining the lock. Lock can judge whether the lock has been obtained;
3. Synchronized will automatically release the Lock. The Lock must be released manually. If the Lock is not released, a deadlock will occur;
4. Synchronized threads (they will enter the blocking state when acquiring the lock), and other threads can only wait for the current thread to release the lock; Lock can try to obtain the current lock, and may not wait all the time;
5. Synchronized reentrant lock, non interruptible, non fair lock; Lock is a reentrant lock. You can judge the status of the lock. It is a non fair lock by default, but you can set it yourself;
6. Synchronized is suitable for locking a small number of code synchronization problems, and Lock is suitable for locking a large number of synchronized code blocks.
What is a lock? How to determine who is the object of the lock?
4. Producer and consumer issues
Interview procedures: single case mode, eight sorting algorithms, producers and consumers, deadlock
Synchronized wait notify is an old version!
The problem exists. There is no problem with the execution of threads a and B; A. If B, C and D threads are started at the same time, can thread synchronization be guaranteed? - spurious wakeup
[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-e4Zzee9r-1640832881517)(D:\APP document \ learning notes \ JAVA.assets\image-20210323210708371.png)]
- Solution: change if word judgment to circular judgment
For the producer and consumer issues of the JUC version, please refer to the JDK source code:
class BoundedBuffer { final Lock lock = new ReentrantLock(); final Condition notFull = lock.newCondition(); final Condition notEmpty = lock.newCondition(); final Object[] items = new Object[100]; int putptr, takeptr, count; public void put(Object x) throws InterruptedException { lock.lock(); try { while (count == items.length) notFull.await(); items[putptr] = x; if (++putptr == items.length) putptr = 0; ++count; notEmpty.signal(); } finally { lock.unlock(); } } public Object take() throws InterruptedException { lock.lock(); try { while (count == 0) notEmpty.await(); Object x = items[takeptr]; if (++takeptr == items.length) takeptr = 0; --count; notFull.signal(); return x; } finally { lock.unlock(); } } }
- Synchronized version: wait() method | notify() method
- Lock version: await() method | signal() method
What are the advantages of the Condition interface Precise notification and wake-up threads
5.8 lock phenomenon - solve the problem of judging the object of the lock
Objects – > multiple / class – > unique
-
8 Lock problem 1--->>Under standard conditions, whether the two threads send text messages first or call first(Send text messages first, then make phone calls)
-
Eight lock problem 2--->>With the addition of asynchronous methods, thread execution is not affected by locks(Execute asynchronous method first); * Two objects and two synchronous methods. Whoever executes first will have a lock to lock the method caller. Those without delay will be executed first
-
Eight lock problem 3--->>Two static synchronization methods are added. The static method is generated when the class is loaded.class Template. All static methods in a class use the same template * Class Template, so static Methods are executed sequentially, regardless of how many objects make method calls
-
Eight lock problem 4--->>A common synchronization method and a static synchronization method, when an object is called; * A common synchronization method and a static synchronization method, when two objects are called; My method is to execute static synchronization first
Summary
-
this keyword can be modified for the instance of new, which is a concrete instance of a class;
-
static Class template is the first mock exam of a class.
6. The collection class is unsafe
List is not safe
- Concurrent modificationexception will be caused!
The solution is as follows:
1,List<String> list = new Vector<>(); 2,List<String> list = Collections.synchronizedList(new ArrayList<>()); 3,List<String> list = new CopyOnWriteArrayList<>(); because Vector The read and write methods in are synchronous methods, which are not as efficient as those in execution CopyOnWriteArrayList The asynchronous method is efficient, CopyOnWriteArrayList Used in Lock Lock. It is flexible to operate the lock status
Set is not safe
The solution is as follows:
1,Set<String> set = Collections.synchronizedSet(new HashSet<>()); Ask dad to help 2,Set<String> set = new CopyOnWriteArraySet<>();
- What is the underlying hashSet?
/** * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has * default initial capacity (16) and load factor (0.75). **/ public HashSet() { map = new HashMap<>(); }
/** * add The underlying essence of method set is map, and the key in hashmap cannot be repeated **/ public boolean add(E e) { return map.put(e, PRESENT)==null; } // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object();
Map is not secure
7. Callable
Similarities and differences between Callable and Runnable
-
Can have return value;
-
Exceptions can be thrown;
-
The implementation methods are different: run()/call()
-
Details:
- 1. Cache to improve efficiency;
- 2. The result may need to wait and block!
8. Common auxiliary classes
8.1 CountDownLatch
Principle:
-
countDownLatch.countDown(); // Initialization quantity minus 1
-
countDownLatch.await(); // Wait for the counter to return to zero, and then execute the following program (for interception). Each time, use the countdown() method to reduce the counter value by 1. When the counter value is 0, the await() method will be awakened and continue to execute the subsequent program!
8.2 CyclicBarrier
for (int i = 1; i <= 7; i++) { final int temp = i; // lambda expressions cannot be manipulated directly i new Thread(()-> { System.out.println(Thread.currentThread().getName() + "Collected" + temp + "A dragon ball"); try { // wait for cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }).start(); }
8.3 Semaphore
Principle:
-
semaphore.acquire(); // Obtain resources. If all resources are used, wait for the resources to be released -- semaphore-1 operation
-
semaphore.release(); // Release resources, - semaphore + 1 operation, waiting for other threads to schedule
effect:
Use of mutual exclusion of multiple shared resources, concurrent flow restriction, and control the maximum number of threads
9. Read write lock
**ReadWriteLock**
Custom cache---ReadWriteLock(Exclusive lock-Write lock[It can only be occupied by one thread at a time];Shared lock-Read lock[It can be occupied by multiple threads at a time]) 1,read-Reading: can coexist; 2,read-Write: cannot coexist; 3,write-Write: cannot coexist
Example:
class MyCacheLock { private volatile Map<String, Object> map = new HashMap<>(); /** * Read / write lock, more fine-grained control **/ private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); /** * Save / write operation */ public void put(String key, Object value) { readWriteLock.writeLock().lock(); try { System.out.println(Thread.currentThread().getName() + "write in" + key); map.put(key, value); System.out.println(Thread.currentThread().getName() + "write in ok"); } catch (Exception e) { e.printStackTrace(); } finally { readWriteLock.writeLock().unlock(); } } /** * Fetch / read operation */ public void get(String key) { readWriteLock.readLock().lock(); try { System.out.println(Thread.currentThread().getName() + "read" + key); Object o = map.get(key); System.out.println(Thread.currentThread().getName() + "read ok"); } catch (Exception e) { e.printStackTrace(); } finally { readWriteLock.readLock().unlock(); } } }
10. Blocking queue
Blocking / queue: [write operation] - if the queue is full, you must block and wait for the read operation; [read operation] - if the queue is empty, it must be blocked waiting for write operation.
- realization:
When will blocking queues be used? - Multithreaded concurrent execution / thread pool using thread queue
- Learn to use queues
Add / remove
Four sets of API s
mode | Throw exception | If there is a return value, no exception will be thrown | Blocking wait | Timeout wait |
---|---|---|---|---|
add to | add() | offer() | put() | offer(E e, long timeout, TimeUnit unit) |
remove | remove() | poll() | take() | poll(long timeout, TimeUnit unit) throws InterruptedException |
Detection and judgment queue header | element() | peek() |
Synchronous queue
There is no capacity. If you enter an element, you must wait for it to be taken out before you can put the element again
-
Synchronization queue-And others BlockQueue Different, SynchronousQueue Do not store elements to the queue put An element must be used first from the inside take Take it out by operation, otherwise it can't be taken out again put Other elements
11. Thread pool (key)
[three methods, seven parameters and four rejection strategies]
**Pooling Technology: * * prepare some resources in advance. If someone wants to use them, read these ready-made resources and return them after use!
- The essence of program operation: it occupies system resources, so pooling technology = = > optimize the use of resources!
Thread pool, connection pool, memory pool, object pool
- Advantages of thread pool:
1. Reduce resource consumption;
2. Improve response speed;
3. Easy to manage.
1. Three methods of thread pool:
// Single thread Executors.newSingleThreadExecutor(); // Create a fixed size thread pool Executors.newFixedThreadPool(5); // Scalable thread pool, strong in case of strength and weak in case of weakness Executors.newCachedThreadPool();
2. Seven parameters of thread pool:
Source code analysis:
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); } public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, // The more is equal to 2.1 billion: it is easy to lead to OOM 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } // Essence: ThreadPoolExecutor() to create a thread pool public ThreadPoolExecutor(int corePoolSize, // Core thread pool size int maximumPoolSize, // Maximum thread pool size long keepAliveTime, // Thread lifetime: it will be released if no one calls it after timeout TimeUnit unit, // Timeout unit BlockingQueue<Runnable> workQueue, // Blocking queue ThreadFactory threadFactory, // Thread factory: creates a thread, which generally does not move RejectedExecutionHandler handler) { // Reject policy if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.acc = System.getSecurityManager() == null ? null : AccessController.getContext(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
Manually create a thread pool:
ExecutorService threadPool = new ThreadPoolExecutor( 2, 5, 3, TimeUnit.SECONDS, new LinkedBlockingDeque<>(3), Executors.defaultThreadFactory(), // When the queue is full, it will try to compete with the oldest thread and will not throw an exception new ThreadPoolExecutor.DiscardOldestPolicy() );
Four rejection strategies:
{new ThreadPoolExecutor.AbortPolicy());}-->If the blocking queue is full and there is thread access, this thread will not be accepted and an exception will be thrown {new ThreadPoolExecutor.CallerRunsPolicy());}-->Go back where you come from! {new ThreadPoolExecutor.DiscardPolicy());}-->When the queue is full, the remaining threads will be lost and no exceptions will be thrown {new ThreadPoolExecutor.DiscardOldestPolicy());}-->When the queue is full, it tries to compete with the oldest thread,No exceptions will be thrown
Summary and extension:
- Understanding: io intensive / cpu intensive
How to set the maximum number of threads in the thread pool:
Custom thread pool: how to define the maximum thread: 1,cpu Intensive: computer cpu For several cores, the maximum thread pool is defined as how large it is, so that it can be maintained cpu Is the most efficient 2,IO Intensive: it is very expensive in the judgment program IO Thread(15 A large mission, io Very resource intensive)
12. Four function interfaces (must be mastered)
- Programmers in the new era: lambda expression, chain programming, functional interface, Stream flow computing.
**Functional interface: * * interface with only one method
- Example:
@FunctionalInterface public interface Runnable { public abstract void run(); } // @Functional interface: simplifies the programming mode and is widely used in the new version of the framework // Foreach (the parameter is the functional interface of the consumer class)
Function: functional interface
// Tool class: output input value Function<String, String> function = str -> str;
Predicate: predicate interface
// Decision interface: there is an input parameter, and its return value can only be boolean value Predicate<String> predicate = String::isEmpty;
Consumer: consumer interface
// Consumer interface: only input, no output Consumer<String> consumer = System.out::println;
Supplier: supply type interface
// Supply type interface: no parameters, only return values Supplier<Integer> supplier = () -> 1024;
13. Stream flow calculation
What is Stream streaming?
- Big data: storage + calculation - > collection. The database is used to store things. All calculations should be handled by the flow!
list.stream() .filter(user -> user.getId() % 2 == 0) .filter(user -> user.getAge() > 23) .map(user -> user.getName().toUpperCase()) .sorted(Comparator.reverseOrder()) .limit(1) .forEach(System.out::println);
14. ForkJoin
What is ForkJoin?
ForkJoin is in jdk1 7 appears and executes tasks in parallel! increase of efficiency. Large amount of data!
-
Big data: Map Reduce
-
ForkJoin features: work stealing - improve thread efficiency
How to use ForkJoin:
-
1. Call through the ForkJoinPool interface:
-
2. Compute task forkjointask Execute (functional interface)
15. Asynchronous callback
Original intention of Future design: to model a Future result
// Send a request - asynchronous callback with no return value CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> { try { TimeUnit.SECONDS.sleep(4); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "runAsync=>Void"); }); System.out.println("1111"); completableFuture.get(); // Get blocking execution results // Asynchronous callback with return value - ajax contains success / failure callback functions CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> { System.out.println(Thread.currentThread().getName() + "runAsync=>Integer"); int i = 10/0; return 1024; }); completableFuture.whenComplete((t, u) -> { System.out.println("t => " + t); // Normal return result System.out.println("u => " + u); }).exceptionally(e -> { System.out.println(e.getMessage()); return 233; });
16. JVM
Understand the Volatile keyword!
Volatile is a lightweight synchronization mechanism provided by java virtual machine!
- 1. Ensure visibility;
- 2. Atomicity is not guaranteed;
- 3. Prohibit instruction rearrangement
What is JMM?
**JMM:**java memory model is an abstract concept or convention!
- 1. Before the thread is unlocked, the shared variable = = must be flushed back to main memory immediately;
- 2. Before locking the thread, the latest stored value must be read into the working memory;
- 3. Locking and unlocking must be the same lock.
8 operations:
Eight operations are defined in the Java memory model, and the virtual machine ensures that each operation is atomic.
- lock: a variable that acts on main memory and identifies a variable as a thread exclusive state.
- unlock: it acts on the main memory variable to release a locked variable, and the released variable can be locked by other threads.
- read: acts on main memory variables and transfers the value of a variable from main memory to working memory.
- load: it acts on the working memory variable and puts the value from read into the variable copy of working memory.
- use: it acts on the working memory variable and passes the value of a variable in the working memory to the execution engine. This operation is executed whenever the virtual machine encounters a bytecode instruction assigned to the variable.
- store: acts on working memory variables and transfers the value of a variable in working memory to main memory.
- write: it acts on the main memory variable and puts the value of the variable obtained from the working memory by the store operation into the main memory variable.
If you want to copy a variable from main memory to working memory: perform read and load operations in sequence.
If you want to synchronize variables from working memory, the main memory: store and write operations are performed sequentially.
17. Volatile
1. Ensure visibility
private static volatile int num = 0; // volatile keyword decoration ensures visibility
2. Atomicity is not guaranteed – indivisible (threads cannot be disturbed or split when executing tasks. They either succeed or fail at the same time!)
// Theoretically 20x1000=20000 for (int i = 1; i <= 20; i++) { new Thread(()-> { for (int j = 0; j < 1000; j++) { add(); } }).start(); } while (Thread.activeCount() > 2) { Thread.yield(); } System.out.println(Thread.currentThread().getName() + " " + num); // Execution result: main 15595 (less than 20000)
If Lock and Synchronized locks are not applicable, if atomicity is guaranteed?
- The operations of these classes are directly linked to the operating system to modify the value in memory! Unsafe class is a very special class!
What is instruction rearrangement?
- When the program is executed, the computer does not execute in the order you write.
Source code - compiler optimized rearrangement - instruction parallelism may also be replayed - memory system will also be replayed - Execution
- When the processor rearranges instructions, it needs to consider the dependence between data
int x = 1; // 1 int y = 2; // 2 x = x + 5; // 3 y = x * x; // 4 // Desired operation 1234, but 2134 / 1324 can achieve the same effect // It can't be 4123
Thread A | Thread B |
---|---|
x = a | y = b |
b = 1 | a = 2 |
Normal results: x = 0; y = 0. However, the order in the following table may also occur due to instruction rearrangement!
Thread A | Thread B |
---|---|
b = 1 | a = 2 |
x = a | y = b |
Weird result caused by instruction reordering: x = 2; y = 1.
volatile can avoid instruction rearrangement!
Memory barrier / CPU instruction function:
- 1. Ensure the normal sequence of specific operations;
- 2. Memory visibility of some variables can be guaranteed.
18. Singleton mode
Hungry man style DCL lazy man style, deep study!
package com.juc.singleton; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; /** * @Description: Lazy singleton mode * @author: L-B-S * @Date: 2021/3/26 18:37 * @modified_By: * @Version: 0.0$ */ public class Lazy { private static volatile Lazy lazy; private static boolean flag = false; private Lazy() { synchronized (Lazy.class) { if (!flag) { flag = true; } else { throw new RuntimeException("Do not attempt to break exceptions with reflection"); } } } public static Lazy getInstance() { // Lock if (lazy == null) { synchronized (Lazy.class) { if (lazy == null) { // Not an atomic operation: 1. Allocate memory space; 2. Execute the construction method and initialize the object; 3. Point this object to memory space lazy = new Lazy(); } } } return lazy; } // Safety under single thread public static void main(String[] args) throws Exception { // Lazy instance1 = Lazy.getInstance(); Field flag = Lazy.class.getDeclaredField("flag"); flag.setAccessible(true); Constructor<Lazy> declaredConstructor = Lazy.class.getDeclaredConstructor(null); declaredConstructor.setAccessible(true); Lazy instance1 = declaredConstructor.newInstance(); flag.set(instance1, false); Lazy instance2 = declaredConstructor.newInstance(); System.out.println(instance1 == instance2); } }
19. Deeply understand CAS - cultivate internal skills
What is CAS?
- Non spin lock used at the bottom of CAS: when comparing the value in the current working memory with the value in main memory, if this value is the expected value, subsequent operations will be performed; Otherwise, it will wait in a cycle!
- Disadvantages:
- 1. The cycle will take time;
- 2. One time can only guarantee the atomicity of one shared variable;
- 3. It can easily lead to ABA problems.
CAS core issue: ABA issue (for short: civet cat for Prince)
// Troublemaker thread AtomicInteger atomicInteger = new AtomicInteger(2020); System.out.println(atomicInteger.compareAndSet(2020, 2021)); System.out.println(atomicInteger.get()); System.out.println(atomicInteger.compareAndSet(2021, 2020)); System.out.println(atomicInteger.get()); // Expected thread System.out.println(atomicInteger.compareAndSet(2020, 6666)); System.out.println(atomicInteger.get());
20. Atomic reference
Solution to ABA problem: atomic reference is introduced to solve it perfectly. There will be version records for each change!
package com.juc.cas; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicStampedReference; /** * @Description: CAS---CPU Concurrent primitives! * @author: L-B-S * @Date: 2021/3/26 20:17 * @modified_By: * @Version: 0.0$ */ public class CASDemo { public static void main(String[] args) { // int Integer note: if the generic is a wrapper class, pay attention to the reference of objects during comparison AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(1, 1); new Thread(() -> { // Get version number int stamp = atomicStampedReference.getStamp(); System.out.println("a1 => " + stamp); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(atomicStampedReference.compareAndSet(1, 2, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1)); System.out.println("a2 => " + atomicStampedReference.getStamp()); System.out.println(atomicStampedReference.compareAndSet(2, 1, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1)); System.out.println("a3 => " + atomicStampedReference.getStamp()); }, "A").start(); new Thread(() -> { int stamp = atomicStampedReference.getStamp(); System.out.println("b1 => " + stamp); try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(atomicStampedReference.compareAndSet(1, 3, stamp, stamp + 1)); }, "B").start(); System.out.println("b2 => " + atomicStampedReference.getStamp()); } }
21. Understanding of various locks
1. Fair lock
Fair lock: very fair (no jumping in line)
Unfair lock: very unfair (you can jump in the queue, which is unfair by default)
/** * Creates an instance of {@code ReentrantLock}. * This is equivalent to using {@code ReentrantLock(false)}. */ public ReentrantLock() { sync = new NonfairSync(); } Lock lock = new ReentrantLock(true); // Overload method: pass in true, which is a fair lock, and false, which is a non fair lock
2. Reentrant lock / recursive lock
The Synchronized keyword implements a reentrant lock
class Phone1 { public synchronized void sendMsg() { System.out.println(Thread.currentThread().getName() + " => sendMsg"); call(); } public synchronized void call() { System.out.println(Thread.currentThread().getName() + " => call"); } }
Lock interface implements reentrant lock
class Phone2 { Lock lock = new ReentrantLock(); public synchronized void sendMsg() { // The first lock -- the lock must be paired, and the lock must be unlocked several times after adding the lock lock.lock(); try { System.out.println(Thread.currentThread().getName() + " => sendMsg"); // Lock inside call method reached call(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public synchronized void call() { // Second lock lock.lock(); try { System.out.println(Thread.currentThread().getName() + " => call"); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }
- Details: attention should be paid to the pairing of locks - that is, if several locks are used, there must be several lock keys (unlocking), otherwise deadlock will occur
3. Spin lock
SpinLock:
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; }
- CAS bottom layer: standard spin lock!
4. Deadlock
What is a deadlock?
- How to troubleshoot / test deadlocks:
Resolve Deadlock:
1. Use jps -l to locate the process number;
D:\java_study\juc-study>jps -l 9936 com.juc.lock.DeadLockDemo 12804 sun.tools.jps.Jps 17828 org.jetbrains.jps.cmdline.Launcher 12872 14024 org.jetbrains.idea.maven.server.RemoteMavenServer36
2. Use the jstack process number to find the deadlock problem
e.printStackTrace(); } finally { lock.unlock(); } } public synchronized void call() { // Second lock lock.lock(); try { System.out.println(Thread.currentThread().getName() + " => call"); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } }
}
- `details`: **Pay attention to the pairing of locks->That is, if several locks are used, there must be several lock keys(Unlock),Otherwise, it will cause deadlock** #### 3. Spin lock > **SpinLock: ** ```java 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; }
- CAS bottom layer: standard spin lock!
4. Deadlock
What is a deadlock?
[external chain picture transferring... (img-A9umsD87-1640832881526)].
- How to troubleshoot / test deadlocks:
Resolve Deadlock:
1. Use jps -l to locate the process number;
D:\java_study\juc-study>jps -l 9936 com.juc.lock.DeadLockDemo 12804 sun.tools.jps.Jps 17828 org.jetbrains.jps.cmdline.Launcher 12872 14024 org.jetbrains.idea.maven.server.RemoteMavenServer36
2. Use the jstack process number to find the deadlock problem