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 }