一:解决多线程的数据问题
为了解决多线程的数据安全问题,java提出了锁的概念:百度了一下网络上对锁的分类及其繁琐并且分类标准不明确。这里稍微按照个人的理解去分类锁。
java为了解决并发的数据问题,实际上提出了2个基本锁的概念,注意这里是指的概念:乐观锁(只在数据提交时验证数据完整性),悲观锁(没一个个操作都验证数据的完整性)。
二:锁的概念和分类
1.定义一个公平锁/非公平锁
公平锁: 多线程获取到锁的顺序按照申请锁的顺序执行(即先到先得)
非公平锁:多线程获取到锁的执行顺序不一定按照申请顺序(即谁先执行谁现货的)
注:(1)java提供了Lock的实现ReentrantLock实现公平锁 new ReentrantLock(true)和非公平锁ReentrantLock(false)
(2) 在应用中非公平锁的吞吐朗大于公平锁(原因是:公平锁和非公平锁都是基于双向链表,公平锁每一次都要从头到尾扫 描然后获取锁,非公平锁都是随机获取并且很大概念获取锁)java中的Synchronized是一把非公平锁。
2.定义一个独享锁/共享锁
独享锁:是指所锁一次只能被一个线程锁占有
共享锁:锁可被多个线程所持有。
注:(1)java中的Lock的ReentrantLock是一把独享锁,ReadWriteLock读是一把共享锁,写是一把独享锁。
(2)独享锁可以保证读取数据的高效性,独享锁可以保证修改线程安全性。
(3)Synchronized是一个独享锁。
3.定义一个互斥锁/读写锁
上面的独享锁/共享锁实际上就是一个该锁的一个具体表现。
4.多线程锁的协作-可重入锁
何为可重入锁,其实这个概念理解起来很抽象,我也是在集合了大量的实例后自己理解出来的。即一个线程执行了,可以在有所的情况下再次进入加锁的方法。这里举出一些比较容易理解的一个私利:
5.锁的载入-自旋锁
在java中,多线程获取到锁一般都是采用循环的方式来在获取锁(就像druid不停的连接数据库一样)。
6.锁量级的优化
重量锁 -》 轻量锁 -》 偏向锁 ,这里特指的是Synchronized的优化,会在以后的章节中单独提出来。
三:java中的锁的基本原理
1.AQS
J简称抽象队列式的同步器,定义了一套多线程访问共享资源的同步器框架,如我们上面所提到的。
(1)AQS维护了一个共享资源(state)和一个等待队列(FIFO,多线程资源竞争被阻赛会进入次队列)。
其中state定义3个方法:getState(),setState(),compareAndSetState() 后面会用到。
(2)AQS定义了资源共享的方式:独占Exclusive(只允许一个线程用到),共享share(允许多线程用到),自定义同步器 只要重写上面的setState()方法,这里方法里可以定义的方法(只要调用即可):
2.CAS
CAS是一种乐观锁技术,默认多线程之间在运行期间不会产生影响,只有在数据提交时才会去比对数据的一致性。
(1)CAS技术需要3个参数:修改数据的内存位置、比较的预期值、写入的新值。具体步骤是,更具位置找到数据,然后与预 期值比对,如果一致就进行写入新智,否则退回。
(2)相对synchronized而言,CAS是一种非阻赛算法的实现。
(3)CAS具有一个缺陷,即预期值先改成其他值,然后又被改成原值提交,这时候CAS是检测不出来的。