笔记_并发编程实践_十三

显式锁
1.Lock和ReentrantLock
(1)Lock提供了无条件的,可轮询的,定时的,可中断的锁获取操作(lock接口的实现必须具有与内部加锁相同的内存可见性语义)

(2)ReentrantLock实现了Lock借口,提供了与synchronized互斥和内存可见性的保证

(3)是有lock方法显示获得锁,使用unlock()方法显示释放锁,由此可知,若然忘记释放锁或者没有在发生异常时对锁进行适当的处理很危险

(4)可轮询的和可定时的锁请求:
<1>使用tryLock方法实现

<2>这样一种方式可以使得在尝试获得锁不成功时,释放已经获得的锁,或者记录失败信息(避免死锁的产生)

<3>使用定时锁,在一定时间内没有获得锁时可以返回,而不会像内部锁一样,会一直阻塞。

(5)可中断的锁获取操作
<1>lockInterruptibly方法能够使你获得锁,并且响应中断
    /**
     * ReatrantLock实现了显示锁Lock接口
     */
    public static Lock lock1 = new ReentrantLock();
    public static Lock lock2 = new ReentrantLock();

    /**
     * 使用显示锁来避免死锁 如在某一方法的执行需要获取两个锁,就肯能由于两个线程各自持有其中一个锁而引发死锁 但是使用显示锁的话
     * 如果或得锁不成功的话就可以作一些处理,而无需向内部锁一样,一直阻塞 这样的话,或得一个锁后若然无法获得第二个锁就会释放
     */
    public static void testTryLock() {
        while (true) {
            if (lock1.tryLock()) {
                try {//注意了,当成功获得锁后,应该考虑发生异常情况下锁的处理,不然会导致锁没有被释放
                    if (lock2.tryLock()) {
                        try {
                            //dosomething
                            return;
                        } catch (Exception e) {

                        } finally {
                            lock2.unlock();
                        }
                    }
                } catch (Exception e) {

                } finally {
                    lock1.unlock();
                }
            }
            try {
                Thread.sleep(Long.parseLong((int) (Math.random() * 1000) + ""));//随机睡眠一定时间后再次尝试
            } catch (InterruptedException ex) {
                Logger.getLogger(MainTest.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public static Boolean testTryLockInTimes(Long milliseSeconds) {
        try {
            if (lock1.tryLock(milliseSeconds, TimeUnit.MILLISECONDS)) {
                try {
                    //dosomething
                    return true;
                } catch (Exception e) {

                } finally {
                    lock1.unlock();
                }
            }
        } catch (InterruptedException ex) {//定时获得显式锁响应中断?
            Logger.getLogger(MainTest.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }

    /**
     * 可相应中断的方式获得锁
     *
     * @return
     */
    public static Boolean lockIntruptly() {
        try {
            lock1.lockInterruptibly();//当其他线程中断当前线程时,获得锁的过程会中断,并抛出异常,响应中断
            try {
            //dosomething

                return true;
            } catch (Exception e) {

            } finally {
                lock1.unlock();
            }
            return false;
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();//恢复中断
            return false;
        }
    }

(6)对性能的考虑
<1>java5中显式锁提供的竞争上的性能远远优于内部锁,java6中两者的性能接近

(7)公平性
<1>reentrantLock构造函数提供了两种公平性的选择 (创建非公平锁或者公平锁)(Semaphore同样提供了公平和非公平的获顺序(收费公平的锁允许闯入,即在锁变为可用时,线程的请求在等待线程的队列中可以跳跃))
<2>公平的获取顺序使得线程的挂起和重新开始的开销更多,性能较差,而很多场景下并不需要保证每一个 线程都按顺序公平获得锁,使用非公平性很多时候可以提供更好的性能
2.在synchronized和ReentrantLock之间进行选择
(1)在内部所不能够满足使用时,才应该使用ReentrantLock(java6后两者的性能已经相差不大,并且使用显式锁有一定危险性,忘记unlock等)
(2)java5中线程转存中无法获得显式锁的信息,java6后需要对管理和调试借口进行注册才能使用

(3)未来的性能优化可能更倾向于内部锁而不是显式锁,应为synchronized是内置于jvm的
3.读写锁
(1)允许多个读者访问或者允许一个写着访问,两者不能同时进行,即读写锁(这一种允许‘读读’的同步,很多应用个程况下更优)
(2)jdk提供ReentrantReadWriteLock,实现了读写锁
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值