Review the basic content of threads
Program: a static program written in a certain language to achieve a specific function and installed on the hard disk
Process: A running program, which is the unit by which the operating system allocates memory space.
Thread: The thread is the smallest execution unit in the process and the CPU scheduling unit. The thread depends on the process.
Create thread
1. Inherit the Thread class and override run()
2. The class implements the Runable interface and overrides run()
Create an object of Thread class and assign tasks to it
3. The class implements the Callable interface, overrides call() to have a return value, and can throw exceptions
Create an object of Thread class and assign tasks to it
Common methods
run() call() start()
set name set priority
Thread status start() ready status
join() sleep() blocking state
yield() The thread gives up the running status and actively gives up ----> ready status
stop() forcibly interrupts the thread (this method is an invalid and expired method)
interrupt() interrupts the thread
Multithreading
Java is one of the first languages to support multi-threaded development.
Java has supported multithreading from the beginning
ability. Since most of today's CPUs are multi-core processors, they can execute multiple threads at the same time.
Advantages of multithreading
Multi-threading technology makes the program more responsive and can be active while doing other work.
Status, program performance is improved.
The essence of performance improvement is to extract the residual value of hardware (hardware utilization).
Multithreading problem
What are the problems caused by multi-threading?
Security (accessing shared variables), performance (cpu switching overhead, etc.)
java concurrent programming
Concurrency and Parallelism
Java Memory Model (JMM)
Note that JMM is a java memory model, not a jvm model.
When Java multi-threading is working, it first reads the data in the main memory into the thread's working memory (cache), then operates the data in the working memory, and writes the data back to the main memory after the operation is completed.
Creating a visibility issue?
The data operated in thread A cannot be seen in thread B.
The operating system may rearrange the order of execution of instructions.
Causes ordering problems
Thread switching comes with atomicity (non-split) issues
i=1; i=1;
i++ -->i=i+1 i++ 2
2
++ is divided into calculation first and then assignment. The ++ operation is not an atomic operation, and the CPU may execute it in two steps.
Core issues of concurrent programming
Core issues of concurrent programming – visibility, atomicity, orderliness
Thread local cache, causing visibility issues
Compilation optimization and rearrangement of instructions cause ordering problems
Thread switching execution will cause atomicity problems
How to solve the problem?
volatile keyword
Shared variables modified by volatile: 1. After operation in one thread, it can be guaranteed to be immediately visible in another thread. 2. Reordering of optimization instructions is prohibited. 3. The atomicity of variable operations cannot be guaranteed.
i++ is not an atomic operation. How to solve the problem of locking?
How to ensure atomicity
"Only one thread is executing at the same time" we call it mutual exclusion. If we can ensure that modifications to shared variables are mutually exclusive, then atomicity can be guaranteed.
Lock
Lock ReentrantLock
synchronized can also guarantee visibility and ordering
Atomic class
java.util.concurrent包
AtomicInteger implements atomic operations through volatile+CAS
getAndIncrement(); is safe instead of i++
CAS can be understood as a spin thought
CAS (Compare-And-Swap) comparison and exchange is suitable for low concurrency situations
CAS is an implementation method of optimistic locking. It adopts the idea of spin and is a lightweight locking mechanism.
Optimistic locking refers to a way that can be solved without locking (that is, there is no lock)
Spin lock (polling) keeps checking in a loop
CAS contains three operands:
①Memory value V
②Estimated value A (the value read again from the memory during comparison)
③Update value B (updated value)
If and only if the expected value A==V, set the memory value V=B, otherwise do nothing.
This approach is more efficient than locking. When the judgment is unsuccessful and the value cannot be updated, it will not block and continue to obtain the CPU.
Right to execute, continue to judge and execute
This approach will not cause thread blocking because there is no lock
shortcoming:
In high concurrency situations, the spin method is used to continuously loop, which has a high CPU usage.
ABA problems may arise. You can add a version number to a class to distinguish whether the value has been changed.
ABA questions
ABA problem, that is, a thread changes the memory value from A to B, and then from B to A. when another
When the thread uses the expected value to judge, the expected value is the same as the memory value, mistakenly thinking that the variable has not been modified.
caused problems.
The main way to solve ABA problems is to avoid ABA problems by using methods like adding version numbers.
For example, the original memory value is (A, 1), and the thread changes (A, 1) to (B, 2), and then (B, 2)
Modify to (A, 3). At this point another thread uses the expected value (A, 1) with the memory value (A, 3)
For comparison, you only need to compare version numbers 1 and 3 to find that the data in the memory has been updated.
JUC class
hashMap is thread-unsafe and cannot be operated concurrently
HashTable is thread-safe and has synchronized modification. Adding the lock directly to put() is inefficient. It is equivalent to locking the entire hash table. It can be used in low concurrency situations. Exclusive lock
ConcurrentHashMap
ConcurrentHashMap is thread-safe. It adopts the lock segmentation mechanism and does not lock the entire hash table. However, segmented locks are not used after jdk8 (create a lock flag object for each position), and it is implemented using CAS idea + synchronized
When inserting, check whether the position corresponding to the hash table is the first node. If so, use the CAS mechanism (loop detection) to insert data into the first position.
If this position already has a value, then the first Node object is used as the lock flag to lock, using the synchronized implementation.
public class HashMapDemo {
/*
HashMap是线程不安全的,不能并发操作的
ConcurrentModificationException 并发修改异常 遍历集合,并删除集合中的数据
Hashtable 是线程安全的 public synchronized V put(K key, V value)-->独占锁
锁直接加到了put方法上,锁粒度比较大,效率比较低
用在低并发情况下可以
Map<String,Integer> map = Collections.synchronizedMap(new HashMap<>());
ConcurrentHashMap
*/
public static void main(String[] args) {
ConcurrentHashMap<String,Integer> map = new ConcurrentHashMap<>();
//模拟多个线程对其操作
for (int i = 0; i < 20; i++) {
new Thread(
()->{
map.put(Thread.currentThread().getName(), new Random().nextInt());
System.out.println(map);
}
).start();
}
}
}