当前位置: 移动技术网 > IT编程>开发语言>Java > Java锁相关知识

Java锁相关知识

2020年03月12日  | 移动技术网IT编程  | 我要评论
1. 锁的分类 Java中目前存在几大类型的锁 - 公平锁/非公平锁:是否按照访问的顺序获取锁。 - 共享锁/独占锁:共享锁可允许多个线程持有,例如读写锁中的读锁。独占锁只允许一个线程占有。 - 可重入锁/不可重入锁:针对同一个线程,是否能重复加锁。在函数互调的时候容易出现。 - 乐观锁/悲观锁:乐 ...

1. 锁的分类

 java中目前存在几大类型的锁

 - 公平锁/非公平锁:是否按照访问的顺序获取锁。

 - 共享锁/独占锁:共享锁可允许多个线程持有,例如读写锁中的读锁。独占锁只允许一个线程占有。 

 - 可重入锁/不可重入锁:针对同一个线程,是否能重复加锁。在函数互调的时候容易出现。

 - 乐观锁/悲观锁:乐观锁的执行流程是:操作前不会加锁,在更新的时候通过版本号和cas来判断是否能执行,适合读多写少的的情况。例如mysql的mvvc。

          悲观锁的执行流程是:操作前必须先获取到锁然后才能进行操作。

 - 条件锁/读写锁:lock.condition,需要满足条件(sinal)才能解锁。读写锁:lock下实现的,其中有读锁和写锁(读读可以,其他只允许一个线程执行),乐观锁。

 ps: cas是通过while循环不断的自旋尝试修改,比较适合锁的时间比较短的场景。

 

2. 锁的理解

 比较通俗的理解就是,锁是相当于临界区的钥匙,当然有不同的锁,不同的钥匙。

 

3. lock和synchronized的区别

 - lock是接口,是jdk层面的。synchronized是java关键字,是jvm层面的。

 - synchronized可以实现自动释放锁,有完善的解锁机制。lock必须手动解锁。

 - lock提供了接口支持锁的状态判断,synchronized不支持。

 - synchronized是独占锁,无法获取锁的线程会堵塞。lock中可以通过trylock判断是否有线程占用了锁,可以防止堵塞

 - synchronized的底层(字节码)是通过monitorenter和monitorexit实现加锁和解锁。lock底层则是通过aqs和cas实现的。

 - synchronized是非公平,独占,可重入的,不可中断。 lock是可公平/非公平,可重入,可中断的。
 ps: aqs=队列+cas

 

4. 锁在java的数据结构中的运用

 1. hashtable: 所有函数都是加了synchronized的,因此是线程安全的,没啥好分析的,性能当然也比较差。

 2. vector:和arraylist不同,是线程安全的。也是通过synchronized实现。

 3. copyonwritearraylist(copyonwritearrayset):读不需要加锁(通过array.copyof直接改变内部map的引用,浪费内存),写是通过reentrantlock加锁实现的线程安全。在读多写少的场景可以大大提升效率。

 4. concurrentlinkedqueue:高效的并发队列,源码解析将在后续整理。通过cas和"wait-free"算法实现

 5. concurrenthashmap:不同于hashtable的加锁方式,在jdk1.7的时候是采用的分段锁的方式大大减少了锁竞争,一个segment里面有一个hash表。采用链表解决hash冲突。在jdk1.8以后采用cas+synchronized锁住node的形式(看看guava的缓存实现方式),同时在同一个node下冲突的节点数量超过阈值则会转化成红黑树,减少查找的时间复杂度。

 ps: concurrenthashmap这种解决并发的算法和思想很值得在工作中借鉴和运用,也是用来考研一个人对于并发的理解深度。

====================================to be continue========================================

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网