• Java高级特性系列--锁机制


    Lock与ReentrantLock

    尽管synchronized在语法上已经足够简单了,在JDK 5之前只能借助此实现,但是由于是独占锁,性能却不高,因此JDK 5以后就开始借助于JNI来完成更高级的锁实现。JDK 5中的锁是接口java.util.concurrent.locks.Lock。另外java.util.concurrent.locks.ReadWriteLock提供了一对可供读写并发的锁。根据前面的规则,我们从java.util.concurrent.locks.Lock的API开始。

    void lock();

    获取锁。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态。

    void lockInterruptibly() throws InterruptedException;

    如果当前线程未被中断,则获取锁。

    如果锁可用,则获取锁,并立即返回。

    如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下两种情况之一以前,该线程将一直处于休眠状态:

    • 锁由当前线程获得;或者
    • 其他某个线程中断当前线程,并且支持对锁获取的中断。

    如果当前线程:在进入此方法时已经设置了该线程的中断状态;或者在获取锁时被中断,并且支持对锁获取的中断,则将抛出 InterruptedException,并清除当前线程的已中断状态。

    Condition newCondition();

    返回绑定到此 Lock 实例的新 Condition 实例。下一小节中会重点谈Condition,此处不做过多的介绍。

    boolean tryLock();

    仅在调用时锁为空闲状态才获取该锁。如果锁可用,则获取锁,并立即返回值 true。如果锁不可用,则此方法将立即返回值false。通常对于那些不是必须获取锁的操作可能有用。

    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

    如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。

    如果锁可用,则此方法将立即返回值 true。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下三种情况之一前,该线程将一直处于休眠状态:

    • 锁由当前线程获得;或者
    • 其他某个线程中断当前线程,并且支持对锁获取的中断;或者
    • 已超过指定的等待时间

    如果获得了锁,则返回值 true

    如果当前线程:在进入此方法时已经设置了该线程的中断状态;或者在获取锁时被中断,并且支持对锁获取的中断,则将抛出 InterruptedException,并会清除当前线程的已中断状态。

    如果超过了指定的等待时间,则将返回值 false。如果 time 小于等于 0,该方法将完全不等待。

    void unlock();

    释放锁。对应于lock()、tryLock()、tryLock(xx)、lockInterruptibly()等操作,如果成功的话应该对应着一个unlock(),这样可以避免死锁或者资源浪费。

    示例如下:

    public class AtomicIntegerWithLock {
    
        private int value;
        private Lock lock = new ReentrantLock();
        public AtomicIntegerWithLock() {
            super();
        }
    
        public AtomicIntegerWithLock(int value) {
            this.value = value;
        }
        public final int getAndSet(int newValue) {
            lock.lock();
            try {
                int ret = value;
                value = newValue;
                return ret;
            } finally {
                lock.unlock();
            }
        }
        public final boolean compareAndSet(int expect, int update) {
            lock.lock();
            try {
                if (value == expect) {
                    value = update;
                    return true;
                }
                return false;
            } finally {
                lock.unlock();
            }
        }
    
        public final int getAndIncrement() {
            lock.lock();
            try {
                return value++;
            } finally {
                lock.unlock();
            }
        }
    }
    

    理论上说Lock的性能比synchronized的要好得多。如果可以的话总是使用Lock替代synchronized是一个明智的选择。但是,随着JVM的发展和优化,synchronized与Lock几乎没有差别了。

  • 相关阅读:
    IIS服务器支持.apk文件下载
    java序列化
    ECMAScript 5/6/7兼容性速查表
    jquery获得select选中索引
    javascript获取调用方法的父引用
    AsyncCTP &IdentityModel
    开源的Owin 的身份验证支持 和跨域支持
    为什么Application_BeginRequest会执行两次
    基于Redis的消息订阅/发布
    基于异步的MVC webAPI控制器
  • 原文地址:https://www.cnblogs.com/IvySue/p/7481419.html
Copyright © 2020-2023  润新知