synchronized锁升级及demo验证

本文详细解析了synchronized锁在JDK1.5与1.6版本中的性能表现及优化,介绍了锁的三种状态:偏向锁、轻量级锁和重量级锁。通过代码示例展示了不同锁状态下的并发性能,并对比了读写锁的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

synchronized锁

我们都知道在jdk 1.5时,synchronized锁是一个重量级锁,缺点如下:

每次获取和释放锁都会带来用户态和内核态的切换,从而增加系统的性能开销 在锁竞争激烈的情况下,synchronized同步锁的性能很糟糕
在JDK 1.5,在单线程重复申请锁的情况下,synchronized锁性能要比Lock的性能差很多

在jdk 1.6时对synchronized进行了优化,大致讲锁分为以下三级

在这里插入图片描述

偏向锁

偏向锁指的是如果一个线程重复的获取锁,那么synchronized锁将会是偏向锁,重复获取锁的开销很低,偏向锁也称为递归锁。

轻量级锁

轻量级锁指的是,当前不只一个线程来获取锁,但是获取锁的线程并没有竞争,也就是说两个线程不同时间的获取锁。

重量级锁

重量级锁指的是不仅有多个线程来获取锁,而且多个线程竞争锁。

代码演示轻量级锁的高效

	/**
     * 查询商品
     * @return
     */
    public static List<String> query(){
        synchronized (map){
            try {
                List<String> good = map.get("good");
                return good;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

200个线程并发请求,处理都是毫秒级的
在这里插入图片描述

我们将线程睡一会,尽量让线程去竞争,这个时候轻量级锁就会升级成重量级锁,代码如下:

 	/**
     * 查询商品
     * @return
     */
    public static List<String> query(){
        synchronized (map){
            try {
                List<String> good = map.get("good");
                Thread.sleep(100);
                return good;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

同样200个线程并发请求,效果如下,截两张图,越下面竞争越激烈,锁的性能也下降的越快。

最上面的线程
在这里插入图片描述

最下面的线程,可以看到原本睡了100毫秒的线程,此时耗时已经接近20秒。
在这里插入图片描述
最后想和大家分享一点的是,重量级锁前面还有一级自旋锁,在高并发的场景下我们也可以尝试关闭自旋锁。

-XX:-UseSpinning // 参数关闭自旋锁优化 (默认打开)   
-XX:PreBlockSpin // 参数修改默认的自旋次数。JDK1.7 后,去掉此参数,由 jvm 控制

在高并发的场景下,我们也可以使用读写锁来进行提高性能,代码如下:

	public class ReadAndWriteLockGoodsCache {

    private static final Map<String, List<String>> map = new HashMap<>();

    private static ReadWriteLock lock = new ReentrantReadWriteLock();

    /**
     * 更新商品
     * @param goodList
     */
    public static void add(String goodList){
        Lock writeLock = lock.writeLock();
        writeLock.lock();
        List<String> good = map.get("good");
        if(good == null){
            good = new ArrayList<>();
        }
        good.addAll(Arrays.asList(goodList.split(",")));
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        map.put("good",good);
        writeLock.unlock();
    }

    /**
     * 查询商品
     * @return
     */
    public static List<String> query() {
        Lock readLock = lock.readLock();
        readLock.lock();
        List<String> good = map.get("good");
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        readLock.unlock();
        return good;
    }
}

由于读锁是共享锁,并不存在竞争关系,而写锁是独占锁,可以保证同步,同样200个线程压测读取数据,效果如下:
在这里插入图片描述
可以看出基本没有竞争锁的开销。

最后

关于并发其实东西还是挺多的,只要一点一点的搞清楚其实并没有想象的那么难,不积硅步无以至千里。

扫码关注公众号

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值