Synchronized/volatile/AtomicInteger/LongAdder总结


Synchronized是悲观锁、独占锁、非公平锁,可以重入,一个线程获得锁,其他线程都要阻塞等待其释放锁,并发性能差,可以保证原子性,线程安全的;

ReentrantLock也是悲观锁,支持公平锁,可重入,与Synchronized相似;

ReadWriteLock读写锁,读锁是共享锁,写锁是独占锁;读写互斥,只允许一个线程写入(其他线程既不能写入也不能读取),没有写入时,多个线程允许同时读(提高性能);

Volatile保证共享变量在内存中的可见性,禁止指令重排序,不保证原子性,多线程下的写有线程安全问题;

AtomicX类使用硬件层面的CAS操作,多线程下,只有一个线程写成功,其他线程自旋尝试,直到成功,保证原子性,线程安全。

LongAdder类与AtomicLong类的区别在于高并发时前者将对单一变量的CAS操作分散为对数组cells中多个元素的CAS操作,取值时进行求和,减少了线程自旋次数;而在并发较低时仅对base变量进行CAS操作,与AtomicLong类原理相同

Atomic操作使用demo:

package com.drz.proxy.internetProxy.util;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 使用两个线程,从给定值0开始一个线程加1循环给定次数,一个减1循环相同次数,如果线程安全,则最后给定值还是0
 *
 */
public class AtomicAndVolatile {

    public static volatile int count = 0; // 计数器

    public static AtomicInteger ai = new AtomicInteger();

    public static final int size = 100000; // 循环测试次数

    public static void main(String[] args) throws InterruptedException {
        // ++ 方式 10w 次
        Thread thread = new Thread(() -> {
            for (int i = 1; i <= size; i++) {
                //                count++;
                ai.incrementAndGet();
            }
        });
        // -- 10w 次

        Thread thread2 = new Thread(() -> {
            for (int i = 1; i <= size; i++) {
                //                count--;
                ai.decrementAndGet();
            }
        });
        thread.start();
        thread2.start();

        thread.join();
        thread2.join();
        //        System.out.println(count); // 打印结果 :count 不为0
        System.out.print(ai.get());//打印结果为0
    }

}
AtomicAndVolatile

ReadAndWriteLock使用demo

 1 package com.drz.proxy.internetProxy.util;
 2 
 3 import java.util.concurrent.ExecutorService;
 4 import java.util.concurrent.Executors;
 5 import java.util.concurrent.locks.ReentrantReadWriteLock;
 6 
 7 public class ReadAndWriteLockTest {
 8 
 9     public static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
10 
11     public static void main(String[] args) {
12         //同时读、写
13         ExecutorService service = Executors.newCachedThreadPool();
14         service.execute(new Runnable() {
15             @Override
16             public void run() {
17                 writeFile(Thread.currentThread());
18             }
19         });
20         service.execute(new Runnable() {
21             @Override
22             public void run() {
23                 readFile(Thread.currentThread());
24             }
25         });
26         service.shutdown();
27     }
28 
29     // 读操作
30     public static void readFile(Thread thread) {
31         lock.readLock().lock();
32 //        boolean readLock = lock.isWriteLocked();
33 //        if (!readLock) {
34             System.out.println("当前为读锁!");
35 //        }
36         try {
37             for (int i = 0; i < 5; i++) {
38                 try {
39                     Thread.sleep(20);
40                 } catch (InterruptedException e) {
41                     e.printStackTrace();
42                 }
43                 System.out.println(thread.getName() + ":正在进行读操作……");
44             }
45             System.out.println(thread.getName() + ":读操作完毕!");
46         } finally {
47             System.out.println("释放读锁!");
48             lock.readLock().unlock();
49         }
50     }
51 
52     // 写操作
53     public static void writeFile(Thread thread) {
54         lock.writeLock().lock();
55 //        boolean writeLock = lock.isWriteLocked();
56 //        if (writeLock) {
57             System.out.println("当前为写锁!");
58 //        }
59         try {
60             for (int i = 0; i < 5; i++) {
61                 try {
62                     Thread.sleep(20);
63                 } catch (InterruptedException e) {
64                     e.printStackTrace();
65                 }
66                 System.out.println(thread.getName() + ":正在进行写操作……");
67             }
68             System.out.println(thread.getName() + ":写操作完毕!");
69         } finally {
70             System.out.println("释放写锁!");
71             lock.writeLock().unlock();
72         }
73     }
74     //    执行结果:
75     //    当前为写锁!
76     //    pool-1-thread-1:正在进行写操作……
77     //    pool-1-thread-1:正在进行写操作……
78     //    pool-1-thread-1:正在进行写操作……
79     //    pool-1-thread-1:正在进行写操作……
80     //    pool-1-thread-1:正在进行写操作……
81     //    pool-1-thread-1:写操作完毕!
82     //    释放写锁!
83     //    当前为读锁!
84     //    pool-1-thread-2:正在进行读操作……
85     //    pool-1-thread-2:正在进行读操作……
86     //    pool-1-thread-2:正在进行读操作……
87     //    pool-1-thread-2:正在进行读操作……
88     //    pool-1-thread-2:正在进行读操作……
89     //    pool-1-thread-2:读操作完毕!
90     //    释放读锁!
91 
92 }