• 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 }
    View Code
  • 相关阅读:
    NHibernate之映射文件配置说明
    JS jQuery json日期格式问题的办法
    Spring.net 配置说明
    NHibernate常见问题及解决方法
    Could not load type 'System.Web.Mvc.ViewPage<dynamic>' in asp.net mvc2 after publishing the website
    启用SQLite的Data Provider 运行WECOMPANYSITE时遇到ERROR CREATING CONTEXT 'SPRING.ROOT': ERROR THROWN BY A DEPENDENCY OF OBJECT 'SYSTEM.DATA.SQLITE'
    Nuget 命令 NuGet 管理项目库
    vs2013(vs2015) 打开vs2010 找不到此项目类型所基于的应用程序 MVC2 升级 MVC5 不能加载Web项目
    JsonResult作为Action返回值时的错误
    MVC 数据验证
  • 原文地址:https://www.cnblogs.com/itfeng813/p/14667933.html
Copyright © 2020-2023  润新知