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带来困惑。总之,是各有利弊,大师们的思想,还需要仔细揣摩啊!

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

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

前言前面介绍了ReentrantLock,又叫排他锁,本篇主要通过CountDownLatch的学习来了解java并发包中是如何实现共享锁的。...
  • yanyan19880509
  • yanyan19880509
  • 2016年08月28日 23:44
  • 6624

共享锁和排它锁(ReentrantReadWriteLock)

1、什么是共享锁和排它锁      共享锁就是允许多个线程同时获取一个锁,一个锁可以同时被多个线程拥有。      排它锁,也称作独占锁,一个锁在某一时刻只能被一个线程占有,其它线程必须等待锁被释...
  • yanlinwang
  • yanlinwang
  • 2014年11月16日 14:27
  • 8861

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

共享模式与独占模式 AQL的内部队列采用的是CLH队列锁模型,CLH队列是由一个一个结点(Node)构成的。Node类中有两个常量SHARE和EXCLUSIVE,顾名思义这两个常量用于表示这个结点支...
  • aesop_wubo
  • aesop_wubo
  • 2012年05月15日 22:39
  • 4489

JAVA 共享锁和条件变量一二

多线程之间需要协调工作。例如,浏览器的一个显示图片的线程displayThread想要执行显示图片的任务,必须等待下载线程downloadThread将该图片下载完毕。如果图片还没有下载完,displ...
  • turkeyzhou
  • turkeyzhou
  • 2010年05月18日 08:37
  • 4683

Java多线程 之 访问共享资源synchronized、lock(七)

上一篇博文引出了资源竞争,并使用例子展示了资源竞争产生的结果(错误)。这篇博文给出解决方法。1. synchronized解决线程冲突的方案基本上都是:序列化访问共享资源。即当多个线程对共享资源同时访...
  • fan2012huan
  • fan2012huan
  • 2016年06月12日 16:07
  • 1369

java中的共享锁与排它锁

什么是共享锁?什么是排他锁?共享锁:如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。排他锁:如果事务T对数据A加上排他锁后,则其他...
  • piaojun_pj
  • piaojun_pj
  • 2010年09月16日 12:53
  • 5008

Java锁(二)ReentrantLock独占锁分析

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

java独占锁ReenTrantLock的实现

ReenTrantLock的实现,源代码分析。
  • qq1004642027
  • qq1004642027
  • 2015年12月26日 18:08
  • 700

AQS源码分析之独占锁和共享锁

AQS实现锁机制并不是通过synchronized——给对象加锁实现的,事实上它仅仅是一个工具类!它没有使用更高级的机器指令,也不靠关键字,更不依靠JDK编译时的特殊处理,仅仅作为一个普普通通的类就完...
  • luofenghan
  • luofenghan
  • 2017年07月13日 15:06
  • 637

多线程基础学习十二:概念了解-重入锁、独占锁与共享锁、公平锁与非公平锁

前面了解了J.U.C中两个重要的类或接口,其它的实现类都是以此为基础的,现在还需要了解一下一些锁的概念,有助于后面学习一些实现类或接口。重入锁在并发中,无论是synchronized还是lock也好,...
  • u010173095
  • u010173095
  • 2017年11月24日 10:50
  • 84
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java并发-独占锁与共享锁
举报原因:
原因补充:

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