In addition to using synchronized, Lock locking, there are many tool classes in Java that can solve concurrency problems without locking
1. Atomic Tools
In JDK 1.8, the classes under the java.util.concurrent.atomic package are all atomic classes, which are based on the implementation of sun.misc.Unsafe.
- To solve concurrency problems, the CPU provides CAS instructions, called Compare And Swap, that is, compare and interact
- The CAS Directive requires three parameters, a variable, a comparison value, and a new value.Update a variable to a new value when its current value is equal to the comparison value
- CAS is a CPU directive that guarantees atomicity at the CPU hardware level
- Atoms in the java.util.concurrent.atomic package are classified as: atomic basic data types, atomic object reference types, atomic arrays, atomic object attribute updates, and atomic accumulators.
Atomic basic data types: AtomicBoolean, AtomicInteger, AtomicLong
Atomic object reference types: AtomicReference, AtomicStampedReference, AtomicMarkableReference
Atomic Array: AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray
Atomic object property update: AtomicIntegerFieldUpdater, AtomicLongFieldUpdater, AtomicReferenceFieldUpdater
Atomic accumulator: DoubleAccumulator, DoubleAdder, LongAccumulator, LongAdder
Modify our previous class for testing atomic problems, using a simple example of AtomicInteger
package constxiong.concurrency.a026; import java.util.concurrent.atomic.AtomicInteger; /** * Testing Atomic Integer * * @author ConstXiong */ public class TestAtomicInteger { // Count variable static volatile AtomicInteger count = new AtomicInteger(0); public static void main(String[] args) throws InterruptedException { // Thread 1 adds 10000 to count Thread t1 = new Thread(() -> { for (int j = 0; j <10000; j++) { count.incrementAndGet(); } System.out.println("thread t1 count Add 10000 to end"); }); // Thread 2 adds 10000 to count Thread t2 = new Thread(() -> { for (int j = 0; j <10000; j++) { count.incrementAndGet(); } System.out.println("thread t2 count Add 10000 to end"); }); // Start Thread 1 t1.start(); // Start Thread 2 t2.start(); // Waiting for thread 1 execution to complete t1.join(); // Waiting for thread 2 execution to complete t2.join(); // Print count variable System.out.println(count.get()); } }
Print results as expected
thread t2 count plus 10000 ends thread t1 count plus 10000 end 20000
2. Thread Local Storage
- The java.lang.ThreadLocal class is used for thread localized storage.
- Thread localized storage is the creation of a variable for each thread in which only the thread can view and modify values.
- A typical use case is when spring uses ThreadLocal to store each thread's own database Connection connection Connection when dealing with database transaction issues.
- When using ThreadLocal, be aware that when you do not use the variable, you must call the remove() method to remove the variable, otherwise memory leaks may occur.
Example
package constxiong.concurrency.a026; /** * Testing Atomic Integer * * @author ConstXiong */ public class TestThreadLocal { // Thread Local Storage Variables private static final ThreadLocal<Integer> THREAD_LOCAL_NUM = new ThreadLocal<Integer>() { @Override protected Integer initialValue() {//initial value return 0; } }; public static void main(String[] args) { for (int i = 0; i <3; i++) {// Start three threads Thread t = new Thread() { @Override public void run() { add10ByThreadLocal(); } }; t.start(); } } /** * Thread local storage variable plus 5 */ private static void add10ByThreadLocal() { try { for (int i = 0; i <5; i++) { Integer n = THREAD_LOCAL_NUM.get(); n += 1; THREAD_LOCAL_NUM.set(n); System.out.println(Thread.currentThread().getName() + " : ThreadLocal num=" + n); } } finally { THREAD_LOCAL_NUM.remove();// Remove variables } } }
The last value of each thread was printed to 5
Thread-0 : ThreadLocal num=1 Thread-2 : ThreadLocal num=1 Thread-1 : ThreadLocal num=1 Thread-2 : ThreadLocal num=2 Thread-0 : ThreadLocal num=2 Thread-2 : ThreadLocal num=3 Thread-0 : ThreadLocal num=3 Thread-1 : ThreadLocal num=2 Thread-0 : ThreadLocal num=4 Thread-2 : ThreadLocal num=4 Thread-0 : ThreadLocal num=5 Thread-1 : ThreadLocal num=3 Thread-2 : ThreadLocal num=5 Thread-1 : ThreadLocal num=4 Thread-1 : ThreadLocal num=5
3,copy-on-write
- According to the English name, it can be seen that write-time replication is required, which reflects a delay strategy.
- The copy-on-write container in Java includes CopyOnWriteArrayList, CopyOnWriteArraySet.
- It involves full replication of arrays, so it's also memory intensive and works well with fewer writes.
A simple example of CopyOnWriteArrayList, which just shows how CopyOnWriteArrayList is used and thread-safe.This scenario is not appropriate for using CopyOnWriteArrayList because it is written more and read less.
package constxiong.concurrency.a026; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.CopyOnWriteArrayList; /** * Test copy-on-write * @author ConstXiong */ public class TestCopyOnWrite { private static final Random R = new Random(); private static CopyOnWriteArrayList<Integer> cowList = new CopyOnWriteArrayList<Integer>(); // private static ArrayList<Integer> cowList = new ArrayList<Integer>(); public static void main(String[] args) throws InterruptedException { List<Thread> threadList = new ArrayList<Thread>(); //Start 1000 threads, add 5 random integers to cowList for (int i = 0; i <1000; i++) { Thread t = new Thread(() -> { for (int j = 0; j <5; j++) { //Hibernate for 10 milliseconds, letting the thread add integers to the cowList at the same time, causing concurrency problems try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } cowList.add(R.nextInt(100)); } }) ; t.start(); threadList.add(t); } for (Thread t : threadList) { t.join(); } System.out.println(cowList.size()); } }
Print results
5000
If the
private static CopyOnWriteArrayList<Integer> cowList = new CopyOnWriteArrayList<Integer>();
Change to
private static ArrayList<Integer> cowList = new ArrayList<Integer>();
The printed result is an integer less than 5000
4. Other concurrent tool classes beginning with Concurrent, such as ConcurrentHashMap, ConcurrentLinkedDeque, ConcurrentLinkedQueue...
- Java Self-Study Guide
- Java interview summary PC-side browsing [click here]
- Java Knowledge Map
- Java Interview Summary Applet Browse, Scan QR Code
All Resource Resources Summarized on Public Number