Lock,了解一下

Lock


public class Test2 {
 /*
  * 显示锁Lock  ReentrantLocak
  *  java.util.concurrent.locks.Lock
  */

//  public void lock() {
//      获取锁,如果锁不可用,出于线程调度目的,将禁用当前线程,获得锁之前,该线程将一直处于休眠状态

//  public void lockInterruptibly() throws InterruptedException {
//      当前线程未被中断,则获取锁,
//      锁可用就立即返回,不可用就禁用当前线程
//      如果当前线程,在进入此方法时设置了该线程的中断状态,或者获取锁时被中断,并且支持对锁获取的中断,则抛出InterruptedException
//      并清楚当前线程的已中断状态

//  public boolean tryLock() {
//      调用时锁为空闲状态才获取锁 可用 true, 不可用 false

//  public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
//      如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁
//      如果锁可用,返回true
//      通常是那些不是必须获取锁的操作

//  public void unlock() {
//      释放锁

//  public Condition newCondition() {
//      返回用来与此lock实例一起使用的condition 实例

    public static void main(String[] args) {

        ReentrantLock reentrantLock = new ReentrantLock();
        /*
         * lock的实现类
         * 是一个互斥的同步锁,
         * 比synchronized 好
         */
            reentrantLock.lock();  // 需要手动开启关闭
            try {
//              只适应用于代码块锁,synchronized 对象之间是互斥关系
            } finally {
                reentrantLock.unlock();
            }
    }
}


读写锁ReentrantReadWriteLock


            ReentrantReadWriteLock reentrantReadWriteLock = new  ReentrantReadWriteLock();
//          可以实现一个方法中读写分离的锁的机制,


            ReadLock readLocak = reentrantReadWriteLock.readLock(); //得到一个可被多个读操作共用的读锁,排斥写锁

            WriteLock writeLock = reentrantReadWriteLock.writeLock();//得到一个写锁,排斥所有其他的读操作和写操作



StampedLock

悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作
读取悲观锁:在读取之前一定要判断一下,数据有没有正在被更改
乐观锁:假定不会发生并发冲突,只在提交操作时检查是否违反数据完整性
读取乐观锁:在读取之前就不需要来判断数据的一致性,只管读就可以了

StampedLock 是基于能力的锁
可以很好的实现悲观锁和乐观锁的逻辑
使用三种模式来控制读/写访问
stampedlock 的状态包含了版本和模式

try 前缀的是 无时间和带时间版本的方法
写:writeLock 可能阻塞等待独占访问,返回一个标识用于unlockWrite以释放锁
读:readLock 可能位非独占访问而阻塞等待,返回一个标志用于方法unlockRead以释放锁

乐观读:只有在锁当前没有以写模式持有,方法validate返回true,可以认为是一种极弱版本的读锁,可以在任意时间被写者打破。

也是利用lock机制,在加上stamp作为锁的标志状态,实现了锁与锁之间的悲观和乐观

比较

synchronized 是在jvm层面上实现的,可以通过一些监控工具监控synchronized的锁定,当代码执行时出现异常,jvm会自动释放锁定。当只是少量竞争者的时候,synchronized是一个很好的通用的锁实现。

reentrantLock 、reentrantReadWriteLock、stampedLock 都是代码块层面的锁定,要保证锁定一定会被释放,就必须将unlock 放到finally中

reetrantlock 是一个很好的通用的锁实现,使用于比较简单的加锁、解锁的业务逻辑,实现复杂的锁机制,当线程增长能够预估计时也是可以的

reetrantReadWriteLock对lock进行了扩展,引入了read和write阻塞和并发机制,相对于reentrantLock,可以实现更复杂的锁机制,且并发性也更高些

stampedlock 又在lock的基础上,实现了可以满足乐观锁和悲观锁等一些在读线程越来越多的业务场景,对吞吐量有巨大的改进

stampedlock 有个复杂的api,不易操作
如果不是业务非得需要建议使用上面两种


volatile 修饰变量

表面意思上是说这个变量是易变的,不稳定的,
所以不要试图对该变量使用缓存等优化机制,
应当每次从它的内存地址中去读值

使用volatile修饰的变量在读取或写入时不需要使用锁,将减少死锁的概率

加锁机制即可以确保可见性,又可以确保原子性
volatile 只提供了内存可见性,而没有提供原子性,做高并发的安全机制的话不可靠

原子操作:atomic

atomic 不会阻塞线程,线程安全的加强版volatile原子操作
利用cpu的比较并交换 cas compare and swap 和非阻塞算法 noblocking algorithms
通过jni java natice interface 为Java本地调用
借助c来调用cpu底层指令实现的

猜你喜欢

转载自blog.csdn.net/java_sparrow/article/details/81222375