Thread 1. Priority
Each thread has a priority, and higher priority threads run first, which means that the probability is higher when allocating CPU time periods.
When a new thread is created on a thread, the line threads the same priority as the thread that created it.
setPriority(int newPriority)
2. Daemon Threads
Each thread may be marked as 1 daemon threads, and it is also when a new thread is created on a thread and if the creation thread is a daemon thread.
When only the daemon is left in the JVM, the daemon does not support the JVM to continue running.
setDaemon(boolean on)
Must be set before start.
When a JVM starts, there is usually a non-daemon thread (running the main function), and the JVM continues to execute threads until:
- The exit method of the runtime class is executed.
- All non-daemon threads have died, or returned from run, or thrown an exception.
3. Common methods 4. Thread Status:
The threads in the JVM have the following States (not the operating system)
- NEW : Thread not yet started
- RUNNABLE : Executing by the JVM, but may be waiting for CPU scheduling
- BLOCKED : Waiting to acquire lock to enter synchronization method/code block
- waiting : Thread in this state waits for another thread to perform a specific operation. Typically
object.wait
After you do the following,
thread.join
,
locksupport.park
- timed_waiting : When a thread begins to wait for some time. Typically
thread.sleep (Long)
,
object.wait (Long)
,
thread.join (long) After you do the following
,
locksupport.parknanos
,
locksupport.parkuntil
- TERMINATED : Thread has ended
Thread.join
is based on the implementation Object.wait
of the. is not discussed with.
Thread.sleep
Typically not used for thread synchronization. He also has nothing to do with locks and does not release locks.
There are 2 main ways to change thread state:
Object.wait
/ Object.notify
This is a JVM-based thread synchronization mechanism that is synchronized
closely related to the keyword, which releases the lock when wait, so you must first acquire the lock by keyword synchronized
.
LockSupport.park
is the new thread state switching mode for the concurrent package. There is synchronized
no relationship between the lock mechanism and the thread state directly, so there is no deadlock problem. Concurrent package All thread state switching is based on this.
Multithreaded Operation 1.volatile
Thread Workspace:
Each thread has its own working memory, which is used to give the JVM a lot of space to optimize the execution of instructions within the thread. The variables in main memory can be copied to the working memory of the thread to execute separately, and at the end of execution, the result can be brushed back to main memory at some time.
Visibility of:
The volatile keyword gives the variable visibility, which is consistent across all the threads in the workspace, and is always the most recent value in the thread, that is, each thread can always see the last write to the volatile variable by another thread.
Cases:
public class Thread1 extends Thread { private Boolean flag = false; public void Run () {if (!flag) { } } public void Close () { flag = true; }}
Call Close () does not stop at all. It needs to be added to flag volatile
. The save is consistent across all thread values.
Principle:
If a write is declared for a volatile variable, the JVM sends a lock prefix instruction to the processor, writing the data from the cache row of the variable to the system memory. But even if you write back to memory, if the other processor cache value is old, and then perform the calculation operation will be problematic, so under multiprocessor, in order to ensure that the cache of the processor is consistent, the cache consistency protocol is implemented, each processor by sniffing the data propagated on the bus to check whether the value of its cache is out of date , when the processor finds that the memory address corresponding to its cache line is modified, the cache line of the current processor is set to an invalid state, and when the processor modifies the data, it forces the data to be read from the system memory into the processor cache.
2.Atomic
atomicity:volatile does not guarantee atomicity. In i++
the process of the most obvious.
private static volatile int value = 0;private Static Class Loopvolatile implements Runnable {public void run () { int count = 0; while (Count < n) { value++; count++;}}} public static void Main (string[] args) { thread T1 = new Thread (new Loopvolatile ()); T1.start (); Thread t2 = new Thread (new Loopvolatile ()); T2.start (); while (t1.isalive () | | t2.isalive ()) { } System.out.println ("Final val be:" + value);} Output:-------------final Val is:1912
value++
This instruction is also divided into 4 JVM instructions, and these 4 instructions are unsafe. Easy to dirty read lost modification. So 2000 additions were made, but the results would not normally be 2000.
The atomic class is meant to solve the problem of atomicity:
These class implementations are also used
volatile
To ensure visibility.
UnSafe
The Atomicinteger class provides an example of the underlying implementation of atomic operations, for instance:
public class Atomicinteger extends number implements Java.io.Serializable { private static final long Serialversionui D = 6214790243416807050L; Setup to uses Unsafe.compareandswapint for updates private static final unsafe unsafe = unsafe.getunsafe ();//For CAs Unsafe class private static final long valueoffset;//value memory address offset unsafe class operation requires static { try { Valueoffset = Unsafe.objectfieldoffset ( AtomicInteger.class.getDeclaredField ("value")) } catch (Exception ex) {throw new Error (ex); } } private volatile int value;//True Value public final Boolean compareandset (int expect, int update) { Return Unsafe.compareandswapint (this, valueoffset, expect, update); } ............}
Resources:
Why volatile cannot guarantee atomicity and atomic can
3.CAS
CAS (Compare and Swap) is a technique that is often used to design concurrency algorithms by comparing and replacing them. Returns a Boolean value.
The assignment action is to replace the old value with the new value, so first compare whether the current value is the old value that you think it is, and if it is not, it means that it has been dirty read. This operation failed to return false.
CAS is not locked for atomic operation. Java's CAs UnSafe
are provided by classes, which are atomic instructions for the underlying implementation, but different CPU architectures may provide an atomic directive that may require some form of internal lock, so the method does not absolutely guarantee that the thread will not be blocked.
Resources:
JAVA CAs principle depth analysis
Lock 1. Lock type
Lock mode:
- Spin lock: With an infinite loop to stop the thread, the thread is always running, taking up CPU but responding faster.
- Blocking Lock: The direct thread enters the blocking state, then resumes the running state, and the thread state switch consumes resources.
- Adaptive spin Lock: The spin-off upper bound of a spin lock is determined by the spin time statistics of the same lock and the holder state of the lock. When the spin exceeds the upper bound, the spin lock is upgraded to a blocking lock.
Fair sex:
- Fair Lock: The order in which threads enter the wait determines the order of recovery
- Non-fair lock: Disorderly sequence when recovering
Pessimism/optimism:
- Pessimistic lock: All related resources are locked at the beginning of 1 transactions. Unlocked after commit. Low efficiency. can prevent dirty reading.
- Optimistic lock: Just commit the transaction when the lock is changed and then unlocked. Cannot prevent dirty reading.
Exclusive/shared:
- Exclusive lock: Only 1 threads hold the lock.
- Shared locks: You can have multiple threads holding locks at the same time.
Resources:
Types and discrimination of Java locks
2.synchronized
Synchronized is the locking mechanism implemented by the JVM. is a reentrant/non-fair/pessimistic/exclusive lock.
Any non-null object can be used as a "lock", and when synchronized acts on a method, the object instance (this) is locked, and the class instance corresponding to the object is locked when acting on a static method.
The synchronized Sync lock is so slow before jdk1.6 that it explodes. 1.6 After a series of optimizations (favor lock, light lock, lock coarsening) performance is similar to lock. Let's talk about the synchronized after 1.6.
This is the Markword part of the object header. Markword will be based on the object state multiplexing space, a total of 4 states, no lock state, biased lock state, lightweight lock state, the weight of the lock state:
Markvalue |
Status |
Status |
Object hash code, object generational age |
01 |
No lock |
The address of the lock record |
00 |
Light weight Lock |
Monitor's address |
10 |
Weight lock |
Empty, do not need to log information |
11 |
GC Flag |
Biased to thread ID, biased timestamp, object generational age |
01 |
Biased lock |
Biased lock
When the lock object is fetched by the thread for the first time, the virtual machine sets the status of the object header to "01", the lock state is biased, and when the lock occurs, it is necessary to check if the ThreadID in the Markvalue is the same as the current thread ID, and the same can be directly re-entered. There is no need to do anything in favor of the release of the lock, which means that the markvalue with the bias lock will always retain the state of the lock, so there is no overhead even if the same thread continues to lock and unlock.
The general bias lock is to upgrade to a lightweight lock when there are different threads requesting a lock, which means that if an object is unlocked by thread 1 plus lock, and then locked by thread 2, there is no lock conflict, and there is a bias lock failure, the difference is that this time to degenerate into a lock-free State, plus a light-weight lock.
Light weight Lock
The condition that a lightweight lock is added to an object is that the object is not currently locked by any other thread.
Adding a lightweight lock creates a lock record in the current thread's stack frame, then sets the Markvalue to the recorded address, the status of the (CAS operation), and if this sequence of operations succeeds, the lightweight lock request succeeds. If unsuccessful, the thread is competing, and a weight lock is generated on the current object for multi-threaded synchronization.
Weight lock
Weight locks are also called object Monitors (monitor) in the JVM.
Once the lock is upgraded to a heavyweight lock, it is no longer restored to the lightweight lock state.
Resources:
Talk about concurrency (ii) synchronized in--java SE1.6
Deep JVM lock Mechanism 1-synchronized
Probe into the implementation of JVM lock 2:synchronized Deep Exploration
Locking mechanism for 3.concurrent packages
The concurrent package is a multithreaded toolkit for Java expansion. Includes many tools, in fact all of its tools are based on the following concepts:
CLH Queue Lock:
The concept of the CLH queue Lock is cool and widely used in many languages, and the Java Lock Lock system is all based on this concept.
A linked list, each of which contains a thread with a status bit. The status bit defaults to True, and false when the release is unlocked.
Lock starts acquiring locks, encapsulates the current thread into a node, and adds a link to the end of the list. and spins to wait for the state of the previous node.
If the previous node releases the lock and the state becomes false, the node spins over and the thread continues until the lock is released.
is to ensure the atomicity of the insertion and removal of nodes through spin locks and atomic.
Resources:
Java Concurrent Programming Learning Note CLH Queue lock
AQS:
AQS (Abstractqueuedsynchronizer) is the basis for the entire java.util.concurrent package. A typical template method pattern.
The AQS is designed with CLH lock as its basis. The wait mechanism is changed from the original spin to block wake.
Wait mechanism: ASQ wraps the thread into a node and maintains a CHL node FIFO queue. But not without brain spin. The spin will be used LockSupport.park()
to suspend itself. LockSupport.unpark(Thread t)
the thread that wakes up the next node when a node is released. Then one spin is processed accordingly.
Timeout measures: The timeout setting is used, and blocking is not used LockSupport.park()
. Instead of judging the spinfortimeoutthreshold variable threshold, it is a split line that determines whether to use spin-off or time-consuming using a system blocking method, and the JUC toolkit author sets the default value to 1000ns by testing. That is, if the remaining time is greater than 1000ns after the successful insertion of the waiting queue, call the system's underlying block, or do not call the system bottom, instead of just let it in the Java application layer continuously cycle consumption time, is the measure of optimization. Jump out of the loop after timeout.
Fair: Aqs can be set to be fair, although he is a FIFO but has an intrusion strategy. The new thread competes with the head node thread.
Status: The entire AQS framework core function is built around its 32-bit integer attribute state, but it gives you the freedom to play, generally speaking it represents the number of locks, the synchronization state control can implement a lot of synchronization tools, such as re-entry locks, semaphores, fences and so on.
To ensure visibility this variable is declared volatile, ensuring that each atomic update is reflected on each thread in a timely manner. There are several ways to do this:
getState()
Normal get
setState(int newState)
The normal set
compareAndSetState(int expect, int update)
The CAS-mode hardware-level atomic update. Returns success or failure.
Resources:
Deep exploration of the principle of reentrantlock realization
Concurrency new feature-lock lock and condition variable
The
reentrantlock
Reentrantlock is a 1 reentrant exclusive lock. Full functionality of synchronized
and can provide fair/non-fair 2 ways.
Reentrantlock internally has Fairsync
and nonfairsync
2 Aqs to be responsible for fairness and injustice.
This is the logic of Reentrantlock's Fair mode lock when attempting to acquire a lock.
abstract static class Sync extends Abstractqueuedsynchronizer {...} Static final class Fairsync extends Sync {final void lock () {acquire (1); } Protected Final Boolean tryacquire (int acquires) {final Thread current = Thread.CurrentThread (); int c = GetState (); if (c = = 0) {//equals 0 that is not currently locked, start the competition!. if (!hasqueuedpredecessors () &&/* queue has an element (there is a contention failure) */compareandsetstate (0, acquires)) {//compareand SetState also successfully indicates a competitive success setexclusiveownerthread (current);//Set this thread to the exclusive lock holder thread return true; }} else if (current = = Getexclusiveownerthread ()) {//Lock has been used, but the thread of the consumer is itself, this is the case of re-entry. int NEXTC = c + acquires; if (NEXTC < 0) throw new Error ("Maximum lock count Exceeded"); SetState (NEXTC);//state+1 return true; }//Other cases indicate that the lock cannot be acquired. return false; }}
Condition
Condition is used in conjunction with lock to Lock#newCondition()
create a condition instance that is bound to lock.
await()
Corresponds toObject#wait()
signal()
Corresponds toObject#notify()
signalAll()
Corresponds to Object#notifyAll()
.
Of course these methods synchronized
are the same as the need to Lock#lock()
acquire locks first.
Blockingqueue
A concept that arises entirely from the concept of consumer production.
Common subcategories are ArrayBlockingQueue
,LinkedBlockingQueue
constructor to set a capacity. The default is maximum int.
When adding data, check whether the capacity limit is reached and the upper limit is blocked until it is consumed;
Check to see if no data has been removed and block until data is added.
Internal Use ReentrantLock
+ Condition
to achieve.
Reentrantreadwritelock
Read-write Lock: Allows reading, reads and writes, write concurrency is not allowed. is a reentrant shared lock.
Semaphore
Semaphore: The operating system's semaphore is a very important concept, set N licenses (i=n), the thread takes 1 licenses (i--) to access the resources, the end of the visit to release the license (i++). I=0 when the license is not available, wait for the license.
The semaphore in Java is also implemented through AQS. Constructs a method to pass in the number of licenses, through a simple 2 method semp.acquire()
semp.release()
. The number of licenses is 1 o'clock equivalent to Reentrantlock.
Countdownlatch
You can implement a counter-like function. The thread that is blocked with this counter will be unblocked when the count becomes 0 o'clock.
Constructs a method to pass in a count, by simply 2 methods await()
countDown()
.
Cyclicbarrier
A loopback fence that allows a group of threads to wait until a certain state has been executed.
The Cyclicbarrier constructor passes in the number of fences, using await()
blocking the current thread, and releasing all threads while blocking the number of threads equal to the number of fences.
Thread pool
The thread pool is primarily designed to address the performance cost of thread creation and thread destruction.
Java provides four thread pools through executors, namely:
- Newcachedthreadpool
Creates a cacheable thread pool that can flexibly reclaim idle threads if the thread pool length exceeds the processing needs, and creates a new thread if it is not recyclable.
- Newfixedthreadpool
Creates a thread pool that controls the maximum number of concurrent threads, and the excess threads wait in the queue.
- Newscheduledthreadpool
Create a fixed-line pool that supports timed and recurring task execution.
- Newsinglethreadexecutor
Creates a single threaded thread pool that performs tasks with only a single worker thread, ensuring that all tasks are executed in the specified order (FIFO, LIFO, priority).
The implementation principle is also an infinite loop processing runable. Multiple threads share a task queue, LinkedBlockingQueue
implemented with.
Translation from void execute(Runnable command)
the source notes, slightly modified:
Perform runable in 3 steps:
- If you are running fewer threads than Corepoolsize, try to start creating a new 1 thread and take the task as his first task, atomically call Addworker and check runstate and Workercount, no need to add the queue.
- Try adding the queue, and if it succeeds, we still need to double check to see if we need to add 1 new threads (because there is a case where the thread Cheng one by one threads at the end of the next check), check that the thread pool is closed, and reject the current task after it has ended.
- If we can't get into the queue, we'll try to add 1 new threads, and if we fail we'll know we're closed or we're saturated. So I refused to drop the task.
The thread pool is loaded with Worker,worker, which is a 1 aqs that encapsulates 1 thread.
Create 1 new workers with initial tasks or add tasks to the queue and create 1 empty workers as per the above rules.
New The worker will start its thread. The run()
following method is executed directly in this thread (the code is Simplified):
void Runworker (Worker w) { w.unlock ();//Allow interrupts while (task! = NULL | | (Task = Gettask ()) = null) { w.lock ();//simple use of Aqs to implement mutexes and cannot be re-entered. beforeexecute (WT, task); try { task.run (); } finally { AfterExecute (task, thrown); } W.unlock (); }}
private Runnable getTask()
Use LinkedBlockingQueue
get runable. So when there is no pending task, it blocks until it wakes up.
Resources:
Use of the Java four thread pool
I have a public number that often shares some of the dry stuff related to Java technology, and if you like my share, you can use the search for "Java leader" or "Javatuanzhang" for attention.
Java multithreaded Deep Exploration