在java高并发编程,有几个很重要的内容:java
1.CAS算法算法
2.CPU重排序数据库
3.缓存行伪共享编程
咱们先来讲说高并发世界中的主要关键问题是什么?缓存
是数据共享。多线程
由于多线程之间要共享数据,就会遇到各类问题。以下图:架构
若是两个线程同时写入,那怎么保证数据的一致性?是线程1先写,仍是线程2先写,这是个问题。那要如何解决这个问题?并发
答案是:加锁。数据库设计
好比,线程1先访问共享数据区,那么它就先把这块数据区锁起来。后面若是其余线程要访问这个共享区,首先要从线程1这里获取锁,才能进一步访问这个共享区。这里很好理解,高并发
其实至关于这样的情景,你有一个抽屉,抽屉有把锁,这个锁的钥匙,在你手上,你就能够打开抽屉,往里面存放或拿取物件。其余人,要从这个抽屉里存放东西,必须征得你的赞成,从你手上拿到钥匙,而后,他才能用这把钥匙打开抽屉,进行存放物件的动做。以下图:
回到高并发的线程世界,咱们知道,能够用加锁来解决多线程访问共享数据区的问题。那问题又来了,那这把锁,先交给谁呢?怎么解决这个问题呢?
答案是:锁竞争。
多线程,若是在优先级同样的状况下,你们进行公平竞争?那怎么样才算公平竞争呢?通常状况下,咱们均可以想到:先到先得。
是的,通常状况下,操做系统对线程竞争,都取用这个方式,这样也符合常理。
好,线程1来了,得到一把锁,对这个共享数据区进行锁定访问。那别的线程,只能等待这个线程“办完事”后,释放锁。这时,这些别的线程就进入等待状态。
如今问题,又来了,若是线程1只是对这个共享数据区进行读访问,是否有必要把这个数据区全面锁定,不让其余线程进行读访问呢?
没有必要!
怎么解决?
读写分离!
分别定义两把锁,一把读锁,一把写锁。写锁,仍是对写有独占权。读锁,就能够无限量地分发给其余多个线程。这样不影响共享数据区的数据一致性。
其实,读写分离,是架构设计和数据库设计中一个很重要的设计思想,也是高性能的一种设计理念。
固然,锁有不少种,如下就是各类锁:
锁 |
优势 |
缺点 |
适用场景 |
偏向锁 |
加锁和解锁不须要额外的消耗,和执行非同步方法比仅存在纳秒级的差距。 |
若是线程间存在锁竞争,会带来额外的锁撤销的消耗。 |
适用于只有一个线程访问同步块场景。 |
轻量级锁 |
竞争的线程不会阻塞,提升了程序的响应速度。 |
若是始终得不到锁竞争的线程使用自旋会消耗CPU。 |
追求响应时间。 同步块执行速度很是快。 |
重量级锁 |
线程竞争不使用自旋,不会消耗CPU。 |
线程阻塞,响应时间缓慢。 |
追求吞吐量。 同步块执行速度较长。 |
好了,今天,咱们主要讲多线程高并发编程的核心概念:线程锁。
明天,咱们继续讲锁的底层实现原理。