• java高并发核心要点|系列1|开篇


    在java高并发编程,有几个很重要的内容:

    1.CAS算法

    2.CPU重排序

    3.缓存行伪共享

    我们先来说说高并发世界中的主要关键问题是什么?

    是数据共享。

    因为多线程之间要共享数据,就会遇到各种问题。如下图:

    如果两个线程同时写入,那怎么保证数据的一致性?是线程1先写,还是线程2先写,这是个问题。那要如何解决这个问题?

    答案是:加锁。

    比如,线程1先访问共享数据区,那么它就先把这块数据区锁起来。后面如果其他线程要访问这个共享区,首先要从线程1这里获取锁,才能进一步访问这个共享区。这里很好理解,

    其实相当于这样的情景,你有一个抽屉,抽屉有把锁,这个锁的钥匙,在你手上,你就可以打开抽屉,往里面存放或拿取物件。其他人,要从这个抽屉里存放东西,必须征得你的同意,从你手上拿到钥匙,然后,他才能用这把钥匙打开抽屉,进行存放物件的动作。如下图:

     回到高并发的线程世界,我们知道,可以用加锁来解决多线程访问共享数据区的问题。那问题又来了,那这把锁,先交给谁呢?怎么解决这个问题呢?

    答案是:锁竞争。

    多线程,如果在优先级一样的情况下,大家进行公平竞争?那怎么样才算公平竞争呢?一般情况下,我们都可以想到:先到先得。

    是的,一般情况下,操作系统对线程竞争,都取用这个方式,这样也符合常理。

    好,线程1来了,获得一把锁,对这个共享数据区进行锁定访问。那别的线程,只能等待这个线程“办完事”后,释放锁。这时,这些别的线程就进入等待状态。

    现在问题,又来了,如果线程1只是对这个共享数据区进行读访问,是否有必要把这个数据区全面锁定,不让其他线程进行读访问呢?

    没有必要!

    怎么解决?

    读写分离!

    分别定义两把锁,一把读锁,一把写锁。写锁,还是对写有独占权。读锁,就可以无限量地分发给其他多个线程。这样不影响共享数据区的数据一致性。

    其实,读写分离,是架构设计和数据库设计中一个很重要的设计思想,也是高性能的一种设计理念。

    当然,锁有很多种,以下就是各种锁:

    优点

    缺点

    适用场景

    偏向锁

    加锁和解锁不需要额外的消耗,和执行非同步方法比仅存在纳秒级的差距。

    如果线程间存在锁竞争,会带来额外的锁撤销的消耗。

    适用于只有一个线程访问同步块场景。

    轻量级锁

    竞争的线程不会阻塞,提高了程序的响应速度。

    如果始终得不到锁竞争的线程使用自旋会消耗CPU。

    追求响应时间。

    同步块执行速度非常快。

    重量级锁

    线程竞争不使用自旋,不会消耗CPU。

    线程阻塞,响应时间缓慢。

    追求吞吐量。

    同步块执行速度较长。

    好了,今天,我们主要讲多线程高并发编程的核心概念:线程锁。

    明天,我们继续讲锁的底层实现原理。

    本人精通java高并发,DDD,微服务等技术实践,专注java,rust技术栈。 本人姓名郭莹城,坐标深圳,前IBM架构师、咨询师、敏捷开发技术教练,前IBM区块链研究小组成员、十多年架构设计工作经验,《区块链核心技术与应用》作者之一, 现聚焦于:区块链创投与交易所资源对接和技术咨询。 工作微信&QQ:360369487,区块链创投与交易所资源对接,加我注明:博客园+对接,技术咨询和顾问,加我注明:博客园+顾问。想学习golang和rust的同学,也可以加我微信,备注:博客园+golang或博客园+rust,谢谢!
  • 相关阅读:
    16.14
    16.13
    JAVA JLabel自定义子类无法显示
    16.12
    16.11
    css实现垂直居中
    HTML5学习笔记
    HTML、Css中插入图片的一些问题
    MySQL的if函数
    java实现将汉字转为首字母、拼音
  • 原文地址:https://www.cnblogs.com/gyc567/p/11014782.html
Copyright © 2020-2023  润新知