Java中的锁
Posted gluawwa
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中的锁相关的知识,希望对你有一定的参考价值。
Java中锁的概念
自旋锁:为了不放弃CPU事件,循环使用CAS尝试对数据进行更新,直至成功。
悲观锁:假定会发生并发冲突,对所有操作加锁
乐观锁:假定没有冲突,在修改数据时如果发现数据与之前获取的不一致,则读取最新数据,修改后重试修改
独享锁(写):给资源加上写锁,线程可以修改资源,其他线程不能再获取锁
共享锁(读):给资源加上独锁后只能读不能写,其他线程也只能加读锁
可重入锁、不可重入锁:线程拿到锁后,可以自由进入同一把锁所同步的其他代码
公平锁、非公平锁:争抢锁的顺序,如果是按先来后到的原则,则是公平的
几种重要的锁的实现:synchronized、Reentranlock、ReenTranReadWriteLock
同步关键字synchronized
属于最基本的线程通信机制,基于对象监视器实现的
Java中每个对象都与一个监视器相关联,一个线程可以加锁或者解锁
一次只有一个线程可以锁定监视器
试图锁定该监视器的任何其他线程都会被阻塞,直到它们可以获得线程上的监视器为止
特性:可重入、独享、悲观锁
范围:类锁、对象锁、锁消除、锁粗化
同步关键字,不仅是实现同步,根据JMM规定还能保证内存可见性(读取最新主内存数据,结束后写进主内存)
同步关键字加锁原理
当有线程对对象进行加锁操作时,会修改对象Mark Word中的内容,以下是偏向锁到轻量级锁的过程
偏向标记第一次有用,当出现争抢以后就没用了。-XX:UseBiasedLocking禁止使用偏置锁定
偏向锁,本质上是无锁,当有线程对对象加锁时,只需比对thread ID。如果没有发生过多线程争抢锁的情况,JVM就认为是单线程的,无需去做同步
重量级锁--监视器(monitor)
修改Mark Word如果失败,会自旋CAS一定次数,该次数可以通过参数配置:
超过次数,仍未抢到锁,则升级为重量级锁,进入阻塞。
monitor也叫管程。一个对象会有一个对应的monitor。
锁降级
锁降级指的是写锁降级为读锁。把持住当前拥有的写锁的同时,再获取到读锁,最后释放写锁的过程。这里使用
ReentrantReadWriteLock中的代码示例。
/* <p><b>Sample usages</b>. Here is a code sketch showing how to perform lock downgrading after updating a cache (exception handling is particularly tricky when handling multiple locks in a non-nested fashion): */ class CachedData { Object data; volatile boolean cacheValid; final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); void processCachedData() { rwl.readLock().lock(); if (!cacheValid) { // Must release read lock before acquiring write lock rwl.readLock().unlock(); rwl.writeLock().lock(); try { // Recheck state because another thread might have // acquired write lock and changed state before we did. if (!cacheValid) { data = ... cacheValid = true; } // Downgrade by acquiring read lock before releasing write lock rwl.readLock().lock(); } finally { rwl.writeLock().unlock(); // Unlock write, still hold read } } try { use(data); } finally { rwl.readLock().unlock(); } } }}
以上是关于Java中的锁的主要内容,如果未能解决你的问题,请参考以下文章