java并发-独占锁与共享锁

原创 2014年12月31日 11:34:45

1 锁的独占与共享

      java并发包提供的加锁模式分为独占锁和共享锁,独占锁模式下,每次只能有一个线程能持有锁,ReentrantLock就是以独占方式实现的互斥锁。共享锁,则允许多个线程同时获取锁,并发访问 共享资源,如:ReadWriteLock。AQS的内部类Node定义了两个常量SHARED和EXCLUSIVE,他们分别标识 AQS队列中等待线程的锁获取模式。

     很显然,独占锁是一种悲观保守的加锁策略,它避免了读/读冲突,如果某个只读线程获取锁,则其他读线程都只能等待,这种情况下就限制了不必要的并发性,因为读操作并不会影响数据的一致性。共享锁则是一种乐观锁,它放宽了加锁策略,允许多个执行读操作的线程同时访问共享资源。 java的并发包中提供了ReadWriteLock,读-写锁。它允许一个资源可以被多个读操作访问,或者被一个 写操作访问,但两者不能同时进行。

2 锁的公平与非公平

     锁的公平与非公平,是指线程请求获取锁的过程中,是否允许插队。在公平锁上,线程将按他们发出请求的顺序来获得锁;而非公平锁则允许在线程发出请求后立即尝试获取锁,如果可用则可直接获取锁,尝试失败才进行排队等待。ReentrantLock提供了两种锁获取方式,FairSyn和NofairSync。结论:ReentrantLock是以独占锁的加锁策略实现的互斥锁,同时它提供了公平和非公平两种锁获取方式。最初看源码时竟然把这两个概念弄混了。

 3 AQS提供的模板方法

    AQS提供了独占锁和共享锁必须实现的方法,具有独占锁功能的子类,它必须实现tryAcquire、tryRelease、isHeldExclusively等;共享锁功能的子类,必须实现tryAcquireShared和tryReleaseShared等方法,带有Shared后缀的方法都是支持共享锁加锁的语义。Semaphore是一种共享锁,ReentrantLock是一种独占锁。

    独占锁获取锁时,设置节点模式为Node.EXCLUSIVE

public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

    共享锁获取锁,节点模式则为Node.SHARED

     private void doAcquireShared(int arg) {
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        .....
    }

 4  对ConditionObject的认识

     ReentrantLock是独占锁,而且AQS的ConditionObject只能与ReentrantLock一起使用,它是为了支持条件队列的锁更方便。ConditionObject的signal和await方法都是基于独占锁的,如果线程非锁的独占线程,则会抛出IllegalMonitorStateException。例如signalAll源码:

        public final void signalAll() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            Node first = firstWaiter;
            if (first != null)
                doSignalAll(first);
        }

      我在想,既然Condtion是为了支持Lock的,为什么ConditionObject不作为ReentrantLock的内部类呢?对于实现锁功能的子类,直接扩展它就可以实现对条件队列的支持。但是,对于其它非锁语义的实现类如Semaphore、CountDownLatch等类来说,条件队列是无用的,也会给开发者扩展AQS带来困惑。总之,是各有利弊,大师们的思想,还需要仔细揣摩啊!

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

共享锁和排它锁(ReentrantReadWriteLock)

1、什么是共享锁和排它锁      共享锁就是允许多个线程同时获取一个锁,一个锁可以同时被多个线程拥有。      排它锁,也称作独占锁,一个锁在某一时刻只能被一个线程占有,其它线程必须等待锁被释...

java共享锁实现原理及CountDownLatch解析

前言前面介绍了ReentrantLock,又叫排他锁,本篇主要通过CountDownLatch的学习来了解java并发包中是如何实现共享锁的。...

java中的共享锁与排它锁

什么是共享锁?什么是排他锁?共享锁:如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。排他锁:如果事务T对数据A加上排他锁后,则其他...

java独占锁ReenTrantLock的实现

ReenTrantLock的实现,源代码分析。

Java锁(二)ReentrantLock独占锁分析

ReentrantLock的功能是实现代码段的并发访问控制,是一种排它锁,也就是通常意义上所说的锁,内部有两种实现NonfairSync和FairSync,公平锁和非公平锁,默认采用非公平锁策略。Re...

浅谈Java中的锁

原文地址:http://zhwbqd.github.io/2015/02/13/lock-in-java.html 博主评论:讲得非常易懂,例子也非常好懂,较为全面,先大致看一下AQS的源码会理解的...

java23种设计模式之共享模式(FlyWeight)

http://www.0755build.com 共享模式(FlyWeight)避免拥有相同内容的小类的开销(如耗费内存),使大家同享一个类(元类)。为什么使用共享模式(FlyWeight)呢?因为...

java高并发锁的3种实现

提到锁,大家可能都会想到synchronized关键字,使用它的确可以解决一切并发问题,但是对于系统吞吐要求更高的,在这里提供了几个小技巧,帮助大家减小锁粒度,提高系统并发能力。 ...
  • hl_java
  • hl_java
  • 2017年04月12日 22:36
  • 3781

互斥锁,共享锁,自旋锁 等

 互斥锁(排它锁、独占锁、写锁、X锁)和共享锁(读锁、S锁) 自旋锁               共享锁(S锁):如果事务T对数据A加上共享锁后,则其他事务只能...
  • lisaem
  • lisaem
  • 2015年06月01日 14:58
  • 2066

JAVA并发编程学习笔记之AQS源码分析(共享与互斥)

共享模式与独占模式 AQL的内部队列采用的是CLH队列锁模型,CLH队列是由一个一个结点(Node)构成的。Node类中有两个常量SHARE和EXCLUSIVE,顾名思义这两个常量用于表示这个结点支...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java并发-独占锁与共享锁
举报原因:
原因补充:

(最多只允许输入30个字)