设为首页 加入收藏

TOP

Java并发编程-各种锁(五)
2018-03-18 16:21:30 】 浏览:811
Tags:Java 并发 编程 各种
的与可轮询的锁获取模式,是由tryLock方法实现,与物体爱建的锁获取相比,它具有更完善的错误恢复机制。在内部锁中,死锁是致命的,唯一的恢复方法是重新启动程序,唯一的预防方法是在构建程序时不要出错,


所以不可能循序不一致的锁顺序。可定时的与可轮询的锁提供了另外一个选择:可以规避死锁的放生。


  如果你不能获得所有需要的锁,那么使用可定时的与可轮询的获取方式(tryLock)使你能够重新拿到控制权,它会释放你已经获得的这些锁,然后再重新尝试(或者至少会记录这个失败,抑或者采取其他措施)。使用tryLock试图获得两个锁,


如果不能同时获得两个,就回退,并重新尝试。休眠时间由一个特定的组件管理,并由一个随机组件减少活锁发生的可能性。如果一定时间内,没有获得所有需要的锁,就会返回一个失败状态,这样操作就能优雅的失败了。


tryLock()经常与if esle一起使用。


读-写锁


  ReentrantLock实现了标准的互斥锁:一次最多只有一个线程能够持有相同ReentrantLock。但是互斥通常做为保护数据一致性的很强的加锁约束,因此,过分的限制了并发性。互斥是保守的加锁策略,避免了


“写/写”和“写/读"的重读,但是同样避开了"读/读"的重叠。在很多情况下,数据结构是”频繁被读取“的——它们是可变的,有时候会被改变,但多数访问只进行读操作。此时,如果能够放宽,允许多个读者同时访问数据结构就


非常好了。只要每个线程保证能够读到最新的数据(线程的可见性),并且在读者读取数据的时候没有其他线程修改数据,就不会发生问题。这就是读-写锁允许的情况:一个资源能够被多个读者访问,或者被一个写者访问,两者不能同时进行。


ReadWriteLock,暴露了2个Lock对象,一个用来读,另一个用来写。读取ReadWriteLock锁守护的数据,你必须首先获得读取的锁,当需要修改ReadWriteLock守护的数据,你必须首先获得写入锁。


ReadWriteLock源码接口如下:


public interface ReadWriteLock {
    /**
    * Returns the lock used for reading.
    *
    * @return the lock used for reading
    */
    Lock readLock();


    /**
    * Returns the lock used for writing.
    *
    * @return the lock used for writing
    */
    Lock writeLock();
}


读写锁实现的加锁策略允许多个同时存在的读者,但是只允许一个写者。与Lock一样,ReadWriteLock允许多种实现,造成性能,调度保证,获取优先,公平性,以及加锁语义等方面的不尽相同。


读写锁的设计是用来进行性能改进的,使得特定情况下能够有更好的并发性。时间实践中,当多处理器系统中,频繁的访问主要为读取数据结构的时候哦,读写锁能够改进性能;在其他情况下运行的情况比独占


的锁要稍微差一些,这归因于它更大的复杂性。使用它能否带来改进,最好通过对系统进行剖析来判断:好在ReadWriteLock使用Lock作为读写部分的锁,所以如果剖析得的结果发现读写锁没有能提高性能,把读写锁置换为独占锁是比较容易。


下面我们用synchonized来进行读操作,对于读操作性能如何呢?


例子如下:


public class ReadWriteLockTest {
    private ReentrantReadWriteLock rw1 = new ReentrantReadWriteLock();


    public static void main(String[] args) {
        final ReadWriteLockTest test = new ReadWriteLockTest();


        new Thread(){
            @Override
            public void run() {
                test.get(Thread.currentThread());
            }
        }.start();


        new Thread(){
            @Override
            public void run() {
                test.get(Thread.currentThread());
            }
        }.start();


    }


    public synchronized void get(Thread thread) {


        long start = System.currentTimeMillis();
        while (System.currentTimeMillis() - start <= 1){
            System.out.println(thread.getName() + "正在读操作");
        }
        System.out.println(thread.getName() + "读操作完成");


    }


}


运行结果如下:



可以看到要线程Thread0读操作完了,Thread1才能进行读操作。明显这样性能很慢。


现在我们用ReadWriteLock来进行读操作,看一下性能如何


例子如下:


public class ReadWriteLockTest {
    private ReentrantReadWriteLock rw1 = new ReentrantReadWriteLock();


    public static void main(String[] args) {
        final ReadWriteLockTest t

首页 上一页 2 3 4 5 6 7 下一页 尾页 5/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇二叉搜索树介绍及其接口说明 下一篇在Kotlin中使用Gradle构建缓存

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目