Java线程安全解决方案(synchronized,ReentrantLock,Atomic使用场景描述)

   日期:2020-09-29     浏览:120    评论:0    
核心提示:线程安全解决方案synchronized,ReentrantLock,Atomic 使用场景描述在实际开发过程中如果服务量,请求频繁,就会经常碰见并发,这时候不做处理就会出现很多非法数据。这时候就需要解决线程安全的问题,这时候就可以使用java当中的锁机制。常用有java关键synchronized、可重入锁ReentrantLock,还有并发包下的Atomic 或者Concurrent的安全类型。synchronized使用场景:在资源竞争不是很激烈的情况下,偶尔出现并发,需要同步的情形下,syn

线程安全解决方案

synchronized,ReentrantLock,Atomic 使用场景描述

在实际开发过程中如果服务量,请求频繁,就会经常碰见并发,这时候不做处理就会出现很多非法数据。这时候就需要解决线程安全的问题,这时候就可以使用java当中的锁机制。常用有java关键synchronized、可重入锁ReentrantLock,还有并发包下的Atomic 或者Concurrent的安全类型。

synchronized使用场景:

在资源竞争不是很激烈的情况下,偶尔出现并发,需要同步的情形下,synchronized是很合适的。原因在于,编译程序通常会尽可能的进行优化synchronized,另外可读性非常好,不管用没用过5.0多线程包的程序员都能理解。可以多对方法进行加锁(同步方法),也可以对对象进行加锁(同步代码快)。

    
    private static volatile  Long  syncId=0L;

    
    public static synchronized  Long getSyncId1(){ 
        syncId++;
        return syncId;
    }

    
    public static Long getSyncId2(){ 
        synchronized (syncId){ 
            syncId++;
            return syncId;
        }
    }

代码可读性强,毕竟是java的关键字,执行优先级高。synchronized关键字一放,就解决线程安全的问题。
但是还有一个问题,当前资源竞争激烈时,对于部分线程迟迟获取不到锁,这时候会出现一个锁升级的过程,且锁升级的过程是不可逆的。当从轻量级锁到偏向锁,再到一个重量级锁。性能会大大的降低。
在资源竞争激烈可以使用其他方式来加锁。

ReentrantLock使用场景:

ReentrantLock提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock还能保证正常的性能。
且这个锁可以定义成公平锁还可以定义成非公平锁。

    
    private static volatile Long lockId=0L;

    
    private static final ReentrantLock reentrantLock = new ReentrantLock(true);


    
    public static Long getLockId(){ 
        reentrantLock.lock();
        try { 
            lockId++;
            return lockId;
        }catch (Exception e){ 
            e.printStackTrace();
            return getLockId();
        }finally { 
            reentrantLock.unlock();
        }
    }

我这里以公平锁作为演示对象。ReentrantLock还可以查看锁的状态, 锁是否被锁上了.
可以查看当前有多少线程再等待锁。但是因为ReentrantLock是悲观锁,加锁时会对资源进行加锁,当读取频繁时性能会不如CAS的乐观锁。所以读取频繁使用乐观锁,写入频繁使用悲观锁。

Atomic或者Concurrent使用场景:

和上面的类似,不激烈情况下,性能比synchronized略逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。但是其有一个缺点,就是只能同步一个值,一段代码中只能出现一个Atomic的变量,多于一个同步无效。因为他不能在多个Atomic之间同步。

    
    private static volatile AtomicLong atomicId=new AtomicLong(0L);

    
    public static Long getAtomicId(){ 
        return  atomicId.addAndGet(1);
    }

对于其他类型的比如和Map和Set可以使用用并发包下的ConcurrentHashMap和ConcurrentHashSet等线程安全的数据类型。

    
    private static ConcurrentHashMap<String,String> hashMap = new ConcurrentHashMap<>();
    
    public static void put(String key,String value){ 
        hashMap.put(key,value);
    }

    public static String get(String key{ 
       return hashMap.get(key);
    }

ConcurrentHashMap内部的实现是CAS的乐观锁,当锁无法取得会开始自旋,直到下一次取得锁。

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服