ReentrantLock
reentrant
A single thread can repeatedly enter, but repeatedly exit
interruptible
lockInterruptibly()
Prevents threads from taking up a lot of time because they can’t complete operations late.
Can be timed
If a lock cannot be obtained by timeout, return false, and do not wait forever to form a deadlock
Fair lock
First come, first serve
public ReentrantLock(boolean fair)
public static ReentrantLock fairLock = new ReentrantLock(true);
Example 1:
Standard usage:
Example 2:
The lock can be repeated twice in a row, but must also be unlocked twice, otherwise the thread freezes
Example 3:
interruptible
Lock1. lockInterruptably() in line 23; This method locks, indicating that the lock can be broken, and when broken, an exception is thrown
The last line of code, a daemon thread, checks for deadlocks as follows:
TryLock () can be used for a limited time:
The lock application fails.
The Condition Condition of a reentrant lock
An overview of the
Similar to object.wait () and object.notify () used in conjunction with ReentrantLock
The main interface
void await() throws InterruptedException;
void awaitUninterruptibly();
long awaitNanos(long nanosTimeout) throws InterruptedException;
boolean await(long time, TimeUnit unit) throws InterruptedException;
boolean awaitUntil(Date deadline) throws InterruptedException; void signal();
void signalAll();
The API,
The await() method causes the current thread to wait while releasing the current lock, and when the signal() or signalAll() method is used in another thread, the line regains the lock and continues execution. Or when the thread is interrupted, it can jump out of the wait. This is similar to the object.wait () method.
The awaitUninterruptibly() method is essentially the same as the await() method, but it does not wait for the response to interrupt.
The singal() method is used to wake up a waiting thread. The relative singalAll() method wakes up all waiting threads. This is similar to the obejct.notify () method.
Example:
.awalt () The thread suspends and waits
.signal() wakes up the thread to continue execution and must regain the lock.
Semaphore (Semaphore, shared lock)
Overview Shared locks run multiple threads simultaneously with critical sections,
You can specify how many permissions threads are allowed to enter,
A thread can have one or more permissions, depending on the business logic
Exceeding the specified permissions will act as locks that do not allow threads to enter.
The main interface
// Get semaphore
public void acquire()
// Get semaphore, interrupt is not supported
public void acquireUninterruptibly()
// Try to get semaphore
public boolean tryAcquire()
// Time limit attempt to obtain semaphore
public boolean tryAcquire(long timeout, TimeUnit unit)
// Release semaphore
public void release()
A simple example:
A) acquire B) acquire C) acquire D) acquireRelease ()
Since the permission is 5, there are 20 threads, each with a delay of 2 seconds, so the result is a wave that completes every 2 seconds in four waves
ReadWriteLock (read-write lock)
An overview of the
ReadWriteLock is a read/write separation lock provided in JDK5 that allows multiple read operations. If there is no write operation, all read operations are concurrent without waiting.
All-thread locking can seriously affect performance, so you can use read-write split locking with separate features.
On visit
Read – Read not mutually exclusive: There is no blocking between reads.
Read – write mutex: Read blocks write, and write blocks read.
Write – write mutex: Write blocks.
The main interface
/ / the NEW object
private static ReentrantReadWriteLock readWriteLock=new ReentrantReadWriteLock();
// Get the read lock
private static Lock readLock = readWriteLock.readLock();
// Get the write lock
private static Lock writeLock = readWriteLock.writeLock();
// Lock to unlock
Lock () unlock ()
CountDownLatch
An overview of countdown timers A typical scenario is a rocket launch. Before the launch of a rocket, in order to ensure that everything is safe, often have to carry out the inspection of equipment and instruments. The engine can’t ignite until all the checks are done. This scenario is ideal for CountDownLatch. It can cause the firing thread to wait for all check threads to complete before executing
The main interface
// construct the number of threads that ⏲ counts
static final CountDownLatch end = new CountDownLatch(10);
// Complete a thread
end.countDown();
// Start executing the main thread
end.await();
Schematic diagram
The main thread reaches a critical point and waits for other threads to finish their work before resuming execution.
Example:
CyclicBarrier
An overview of the
Cyclic fence Cyclic means Cyclic, which means the counter can be used over and over again. For example, suppose we set the counter to 10. So after the first batch of 10, 10 threads, the counter will go to zero, and then the next batch of 10 threads
The main interface
public CyclicBarrier(int parties, Runnable barrierAction)
BarrierAction is the action that the system will perform when the counter has finished counting once
await()
Schematic diagram
Code examples:
Note: The last three lines of code interrupt a thread’s operation, so an exception is thrown.
LockSupport (Thread blocking utility class)
An overview of the
Provides a thread blocking primitive
The main interface
// Stop the thread
LockSupport.park();
// The specified thread continues execution
LockSupport.unpark(t1);
Compared with the suspend ()
Less likely to cause thread freezing
Interrupt response
Able to respond to interrupts without throwing exceptions.
The result of the interrupt response is the return of the park() function, which gets the interrupt flag from Thread.interrupted()
The sample
A thread that is park () (suspended) and wants to continue, either unpark or is interrupted, and does not throw an interrupt exception.
The realization of the already
State of the CAS
The mechanism of locking is realized by CAS algorithm, which is the key to reentrant locking
Waiting queue
If the lock is not obtained, the queue is entered and all waiting threads are saved
park()
All waiting threads park (suspend). The first thread, UNLOCK, unpark (unsuspend), and unlock (unlock), and then unlock, and so on.
Concurrent container and typical source code analysis
A collection of packaging
HashMap
Collections.synchronizedMap public static Map m=Collections.synchronizedMap(new HashMap());
This approach is only suitable for cases where the amount of concurrency is small because the implementation uses synchronous locking heavily.
Composition of HashMap:
List
synchronizedList
Again, use a synchronization lock
.Set
synchronizedSet
Again, use a synchronization lock
ConcurrentHashMap
High-performance HashMap
When the put operation is performed, the HashMap is divided into several smaller hashmaps (Segment<K,V>) and the operation is performed to avoid conflicts caused by large HashMap operations between threads.
BlockingQueue
Blocking queue
Thread safe, but not very good performance, in multi-threaded environment can play the role of sharing data
If the data is empty, the thread will wait until another thread writes to the data and wakes up the thread to read the data.
If the data is full, the thread can’t write until another thread has removed the data.
This is called a blocking queue and causes a thread to block
ConcurrentLinkedQueue
High performance linked list queue, same function, better performance, will not cause blocking