java 锁有几种 Java当中有哪几种锁

java\u4e2d\u7684\u9501\u6709\u54ea\u51e0\u79cd

lock\u6bd4synchronized\u6bd4\u8f83\u5982\u4e0b\uff1a

1) \u652f\u6301\u516c\u5e73\u9501\uff0c\u67d0\u4e9b\u573a\u666f\u4e0b\u9700\u8981\u83b7\u5f97\u9501\u7684\u65f6\u95f4\u4e0e\u7533\u8bf7\u9501\u7684\u65f6\u95f4\u76f8\u4e00\u81f4\uff0c\u4f46\u662fsynchronized\u505a\u4e0d\u5230
2) \u652f\u6301\u4e2d\u65ad\u5904\u7406\uff0c\u5c31\u662f\u8bf4\u90a3\u4e9b\u6301\u6709\u9501\u7684\u7ebf\u7a0b\u4e00\u76f4\u4e0d\u91ca\u653e\uff0c\u6b63\u5728\u7b49\u5f85\u7684\u7ebf\u7a0b\u53ef\u4ee5\u653e\u5f03\u7b49\u5f85\u3002\u5982\u679c\u4e0d\u652f\u6301\u4e2d\u65ad\u5904\u7406\uff0c\u90a3\u4e48\u7ebf\u7a0b\u53ef\u80fd\u4e00\u76f4\u65e0\u9650\u5236\u7684\u7b49\u5f85\u4e0b\u53bb\uff0c\u5c31\u7b97\u90a3\u4e9b\u6b63\u5728\u5360\u7528\u8d44\u6e90\u7684\u7ebf\u7a0b\u6b7b\u9501\u4e86\uff0c\u6b63\u5728\u7b49\u5f85\u7684\u90a3\u4e9b\u8d44\u6e90\u8fd8\u662f\u4f1a\u7ee7\u7eed\u7b49\u5f85\uff0c\u4f46\u662fReentrantLock\u53ef\u4ee5\u9009\u62e9\u653e\u5f03\u7b49\u5f85
3) condition\u548clock\u914d\u5408\u4f7f\u7528\uff0c\u4ee5\u83b7\u5f97\u6700\u5927\u7684\u6027\u80fd
JAVA\u4e2d\u9501\u4f7f\u7528\u7684\u51e0\u70b9\u5efa\u8bae\uff1a

1.\u5982\u679c\u6ca1\u6709\u7279\u6b8a\u7684\u9700\u6c42\uff0c\u5efa\u8bae\u4f7f\u7528synchronized\uff0c\u56e0\u4e3a\u64cd\u4f5c\u7b80\u5355\uff0c\u4fbf\u6377\uff0c\u4e0d\u9700\u8981\u989d\u5916\u8fdb\u884c\u9501\u7684\u91ca\u653e\u3002\u9274\u4e8eJDK1.8\u4e2d\u7684ConcurrentHashMap\u4e5f\u4f7f\u7528\u4e86CAS+synchronized\u7684\u65b9\u5f0f\u66ff\u6362\u4e86\u8001\u7248\u672c\u4e2d\u4f7f\u7528\u5206\u6bb5\u9501\uff08ReentrantLock\uff09\u7684\u65b9\u5f0f\uff0c\u53ef\u4ee5\u5f97\u77e5\uff0cJVM\u4e2d\u5bf9synchronized\u7684\u6027\u80fd\u505a\u4e86\u6bd4\u8f83\u597d\u7684\u4f18\u5316\u3002
2.\u5982\u679c\u4ee3\u7801\u4e2d\u6709\u7279\u6b8a\u7684\u9700\u6c42\uff0c\u5efa\u8bae\u4f7f\u7528Lock\u3002\u4f8b\u5982\u5e76\u53d1\u91cf\u6bd4\u8f83\u9ad8\uff0c\u4e14\u6709\u4e9b\u64cd\u4f5c\u6bd4\u8f83\u8017\u65f6\uff0c\u5219\u53ef\u4ee5\u4f7f\u7528\u652f\u6301\u4e2d\u65ad\u7684\u6240\u83b7\u53d6\u65b9\u5f0f\uff1b\u5982\u679c\u5bf9\u4e8e\u9501\u7684\u83b7\u53d6\uff0c\u8bb2\u7a76\u5148\u6765\u540e\u5230\u7684\u987a\u5e8f\u5219\u53ef\u4ee5\u4f7f\u7528\u516c\u5e73\u9501\uff1b\u53e6\u5916\u5bf9\u4e8e\u591a\u4e2a\u53d8\u91cf\u7684\u9501\u4fdd\u62a4\u53ef\u4ee5\u901a\u8fc7lock\u4e2d\u63d0\u4f9b\u7684condition\u5bf9\u8c61\u6765\u548clock\u914d\u5408\u4f7f\u7528\uff0c\u83b7\u53d6\u6700\u5927\u7684\u6027\u80fd\u3002

\u8bed\u6cd5\u5c42\u9762\u8fd8\u662f\u8bed\u8a00\u5c42\u9762\uff1f
\u8bed\u6cd5\u5c42\u9762\u6709synchronized\u548clock\uff0c\u8bed\u8a00\u5c42\u9762\u7684\u770b\u770b\u8fd9\u4e2a\u4e86\u89e3\u4e2a\u5927\u6982\u7f51\u9875\u94fe\u63a5

乐观锁/悲观锁

乐观锁与悲观锁不是指具体的什么类型的锁,而是指看待并发同步的角度。

悲观锁认为对于同一个数据的并发操作,一定是会发生修改的,哪怕没有修改,也会认为修改。因此对于同一个数据的并发操作,悲观锁采取加锁的形式。悲观的认为,不加锁的并发操作一定会出问题。
乐观锁则认为对于同一个数据的并发操作,是不会发生修改的。在更新数据的时候,会采用尝试更新,不断重新的方式更新数据。乐观的认为,不加锁的并发操作是没有事情的。
从上面的描述我们可以看出,悲观锁适合写操作非常多的场景,乐观锁适合读操作非常多的场景,不加锁会带来大量的性能提升。
公平锁/非公平锁

公平锁是指多个线程按照申请锁的顺序来获取锁。

非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。

优点:在于吞吐量比公平锁大。
缺点:可能会造成优先级反转或者某些线程饥饿现象(一直拿不到锁)。
对于Java ReentrantLock而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。
对于Synchronized而言,也是一种非公平锁。由于其并不像ReentrantLock是通过AQS的来实现线程调度,所以并没有任何办法使其变成公平锁。
可重入锁

可重入锁的概念是自己可以再次获取自己的内部锁。
举个例子,比如一条线程获得了某个对象的锁,此时这个对象锁还没有释放,当其再次想要获取这个对象的锁的时候还是可以获取的(如果不可重入的锁的话,此刻会造成死锁)。说的更高深一点可重入锁是一种递归无阻塞的同步机制。
对于Java ReentrantLock而言, 他的名字就可以看出是一个可重入锁,其名字是Re entrant Lock重新进入锁。
对于Synchronized而言,也是一个可重入锁。可重入锁的一个好处是可一定程度避免死锁。
独享锁/共享锁

独享锁是指该锁一次只能被一个线程所持有。
共享锁是指该锁可被多个线程所持有。
对于Java ReentrantLock(互斥锁)而言,其是独享锁。
但是对于Lock的另一个实现类ReadWriteLock(读写锁),其读锁是共享锁,其写锁是独享锁。读锁的共享锁可保证并发读是非常高效的,读写,写读 ,写写的过程是互斥的。
对于Synchronized而言,当然是独享锁。
分段锁

分段锁其实是一种锁的设计,并不是具体的一种锁。对于ConcurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效的并发操作。

我们以ConcurrentHashMap来说一下分段锁的含义以及设计思想,ConcurrentHashMap中的分段锁称为Segment,它即类似于HashMap(JDK7与JDK8中HashMap的实现)的结构,即内部拥有一个Entry数组,数组中的每个元素又是一个链表;同时又是一个ReentrantLock(Segment继承了ReentrantLock)。
当需要put元素的时候,并不是对整个hashmap进行加锁,而是先通过hashcode来知道他要放在那一个分段中,然后对这个分段进行加锁,所以当多线程put的时候,只要不是放在一个分段中,就实现了真正的并行的插入。
但是,在统计size的时候,可就是获取hashmap全局信息的时候,就需要获取所有的分段锁才能统计。
分段锁的设计目的是细化锁的粒度,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作。
互斥锁:

无法获取琐时,进线程立刻放弃剩余的时间片并进入阻塞(或者说挂起)状态,同时保存寄存器和程序计数器的内容(保存现场,上下文切换的前半部分),当可以获取锁时,进线程激活,等待被调度进CPU并恢复现场(上下文切换下半部分)

上下文切换会带来数十微秒的开销,不要在性能敏感的地方用互斥锁
读写锁:

1)多个读者可以同时进行读
2)写者必须互斥(只允许一个写者写,也不能读者写者同时进行)
3)写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)
自旋锁:

自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU。

所有几种来说的话可能有点少三种啊,一般来说的话有手动的,有自动的等等。

扩展阅读:synchronized锁升级过程 ... synchronized锁的是什么 ... java锁 ... javascript入门 ... java入门网站 ... java线程锁有几种 ... jaaaw ... mysql索引 ... java aqs ...

本站交流只代表网友个人观点,与本站立场无关
欢迎反馈与建议,请联系电邮
2024© 车视网