精华内容
下载资源
问答
  • Java 中 ReentrantLock synchronized 都是独占锁共享锁 又叫读锁,指该锁可以被多个线程所持有。Java 中 ReentrantReadWriteLock 其读锁是共享锁,其写锁是独占锁。 读锁的共享锁可保证并发读是非常高效的...

    独占锁

    又叫写锁,指该锁只能被一个线程所持有。Java 中 ReentrantLock 和 synchronized 都是独占锁。

    共享锁

    又叫读锁,指该锁可以被多个线程所持有。Java 中 ReentrantReadWriteLock 其读锁是共享锁,其写锁是独占锁。

    读锁的共享锁可保证并发读是非常高效的,读写,写读,写写的过程是互斥的。

    互斥锁

    在访问共享资源之前对进行加锁操作,在访问完成之后进行解锁操作。 加锁后,任何其他试图再次加锁的线程会被阻塞,直到当前进程解锁。

    加锁前

    代码

    import java.util.HashMap;
    import java.util.Map;
    
    // 模拟缓存操作
    class MyChahe{
    	private volatile Map<String, Object> map = new HashMap<>();
    	
    	public void put(String key, Object value) {
    		System.out.println(Thread.currentThread().getName()+"\t 准备写... "+key+" "+value);
    		try {
    			// 停一会
    			Thread.sleep(300);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		map.put(key, value);
    		System.out.println(Thread.currentThread().getName()+"\t 写完成...");
    	}
    	
    	public Object get(String key) {
    		System.out.println(Thread.currentThread().getName()+"\t 准备读...");
    		try {
    			// 停一会
    			Thread.sleep(300);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		Object object = map.get(key);
    		System.out.println(Thread.currentThread().getName()+"\t 读完成... "+object);
    		return object;
    	}
    }
    
    public class ReadWriteLockDemo {
    	public static void main(String[] args) {
    		MyChahe myChahe = new MyChahe();
    		for (int i = 1; i <= 3; i++) {
    			final int tmpInt = i;
    			new Thread(()->{
    				myChahe.put(tmpInt+"", tmpInt+"");
    			},String.valueOf(i)).start();
    			
    		}
    		for (int i = 1; i <= 3; i++) {
    			final int tmpInt = i;
    			new Thread(()->{
    				myChahe.get(tmpInt+"");
    			},String.valueOf(i)).start();
    			
    		}
    	}
    }

    运行结果

    从运行结果中可以看出,1线程再写入的时候被 2 线程打断,而 2 线程再写入的时候被 3 线程也打断了,最终导致都写入失败了。正常的执行结果应该是 写入->写入成功,中间不允许打断,于是我们给上面的程序进行加锁操作。

    加锁后

    代码

    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    class MyChahe{
    	private volatile Map<String, Object> map = new HashMap<>();
    	// 读写锁
    	private ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock();
    	
    	public void put(String key, Object value) {
    		try {
    			rwlock.writeLock().lock();
    			System.out.println(Thread.currentThread().getName()+"\t 准备写... "+key+" "+value);
    			try {
    				// 停一会
    				Thread.sleep(300);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			map.put(key, value);
    			System.out.println(Thread.currentThread().getName()+"\t 写完成...");
    		} catch (Exception e) {
    			System.out.println(e);
    		}finally {
    			rwlock.writeLock().unlock();
    		}
    	}
    	
    	public Object get(String key) {
    		try {
    			rwlock.readLock().lock();
    			System.out.println(Thread.currentThread().getName()+"\t 准备读...");
    			try {
    				// 停一会
    				Thread.sleep(300);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    			Object object = map.get(key);
    			System.out.println(Thread.currentThread().getName()+"\t 读完成... "+object);
    			return object;
    		} catch (Exception e) {
    			System.out.println(e);
    		}finally {
    			rwlock.readLock().unlock();
    		}
    		return null;
    		
    	}
    }
    
    public class ReadWriteLockDemo {
    	public static void main(String[] args) {
    		MyChahe myChahe = new MyChahe();
    		for (int i = 1; i <= 3; i++) {
    			final int tmpInt = i;
    			new Thread(()->{
    				myChahe.put(tmpInt+"", tmpInt+"");
    			},String.valueOf(i)).start();
    			
    		}
    		for (int i = 1; i <= 3; i++) {
    			final int tmpInt = i;
    			new Thread(()->{
    				myChahe.get(tmpInt+"");
    			},String.valueOf(i)).start();
    			
    		}
    	}
    }
    

    运行结果

    加锁后运行的结果一致了,写操作不可以被其他线程打断,读操作可以同时多个线程同时读取。

    展开全文
  • java并发包提供的加锁模式分为独占锁和共享锁独占锁模式下,每次只能有一个线程能持有锁,ReentrantLock就是以独占方式实现的互斥锁。共享锁,则允许多个线程同时获取锁,并发访问 共享资源,如:ReadWriteLock。...

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

    展开全文
  • 共享锁和独占锁 独占锁:也是悲观锁 synchronized和ReentrantLock 共享锁接口: ReadWriteLock接口 共享锁:该锁可被多个线程共有,典型的就是ReentrantReadWriteLock里的读锁,它的读锁是可以被共享的,但是它的写...
        

    共享锁和独占锁

    独占锁:也是悲观锁
    synchronized和ReentrantLock

    共享锁接口:
    ReadWriteLock接口
    共享锁:该锁可被多个线程共有,典型的就是ReentrantReadWriteLock里的读锁,它的读锁是可以被共享的,但是它的写锁确每次只能被独占。

    reentrantreadwritelock example

    4165335-7f021003e3a423a2.png
    image.png

    展开全文
  • java并发包提供的加锁模式分为独占锁和共享锁独占锁模式下,每次只能有一个线程能持有锁,ReentrantLock就是以独占方式实现的互斥锁。共享锁,则允许多个线程同时获取锁,并发访问共享资源,如:ReadWri..

    转自:https://blog.csdn.net/wojiushiwo945you/article/details/42292999

    另外可以看下这个:https://blog.csdn.net/luofenghan/article/details/75065001

    1 锁的独占与共享

     java并发包提供的加锁模式分为独占锁和共享锁,独占锁模式下,每次只能有一个线程能持有锁,ReentrantLock就是以独占方式实现的互斥锁。共享锁,则允许多个线程同时获取锁,并发访问 共享资源,如:ReadWriteLock。AQS的内部类Node定义了两个常量SHAREDEXCLUSIVE,他们分别标识 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();
        }
    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带来困惑。总之,是各有利弊,大师们的思想,还需要仔细揣摩啊!

     

    展开全文
  • 独占锁共享锁

    千次阅读 2019-08-09 19:38:11
    独占锁共享锁前言概念引入独占锁概念共享锁概念源码分析ReentrantReadWriteLock源码读锁和写锁的具体加锁方式有什么区别 前言 独占锁和共享锁同样是一种概念。我们先介绍一下具体的概念,然后通过ReentrantLock和...
  • Java--独占锁/共享锁

    2019-06-30 11:03:12
    独享锁和共享锁在你去读C.U.T包下的ReeReentrantLock和ReentrantReadWriteLock你就会发现,它俩一个是独享一个是共享锁。 独享锁:该锁每一次只能被一个线程所持有。 共享锁:该锁可被多个线程共有,典型的就是...
  • java中有公平锁、非公平锁、可重入锁(递归锁)、自旋锁、独占锁(写锁)、共享锁(读锁)…… 公平锁 非公平锁 是什么: 公平锁:是指多个线程按照申请的顺序来获取值 非公平锁:是值多个线程获取值的顺序...
  • Java-Lock独占锁共享锁原理

    千次阅读 2018-07-22 09:15:22
    ReentrantLock在使用时需要显式的获取释放,一般用try finally来实现,相对于synchronized,reentrantlock提供了功能更强大的api,例如超时、可中断、公平、非公平、非阻塞获取等等,ReentrantLock是...
  • 将这两个锁之前,我先讲下上一章遗留的...共享锁和独占锁 共享锁,顾名思义,就是这个锁是共享的,咱们能一起使用这个锁。这个就像进男厕所,以前的那种小便池,可以站很多人。 一般共享锁,使用是在读数据的基础上加
  • 独占锁和共享锁

    2017-08-15 20:54:39
    http://www.infoq.com/cn/articles/jdk1.8-abstractqueuedsynchronizerhttp://ifeve.com/java-synchronousqueue/ http://blog.csdn.net/longeremmy/article/details/8231184
  • java中nio独占锁共享锁交互

    千次阅读 2013-08-29 17:08:05
    java,nio中独占锁共享锁交互。 代码使用共享锁实现了reader进程,使用独占锁实现了writer进程。由于锁是与进程而不是Java线程关联的,您将需要运行该程序的多个拷贝。先从一个writer两个或更多的readers开始,...
  • java并发包提供的加锁模式分为独占锁和共享锁独占锁模式下,每次只能有一个线程能持有锁,ReentrantLock就是以独占方式实现的互斥锁。共享锁,则允许多个线程同时获取锁,并发访问 共享资源,如:ReadWriteLock。...
  • 对ReentrantLockSychronized而言都是独占锁。 读锁(共享锁):是指该锁可被多个线程持有。对ReentrantReadWriteLock而言,其读锁是共享锁,其写锁是独占锁。读锁的共享性可保证并发读是非常高效的,读写、写读、...
  • Java - 独占锁(写锁)/共享锁(读锁)/互斥锁 独占锁(写锁): 共享锁: 多个线程同时读一个资源没有任何问题,所以为了满足并发量,读取共享资源应该可以同时进行。 但是 如果有一个线程想去写共享资源来,就不...
  • public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
  • 我们经常听到的独占锁其实就是写锁:一次只能被一个线程占有;共享锁其实就是读锁:多个线程可以同时占有 我们举个例子,先来看看不加读写锁的情况 package com.lt.ReadWriteLock; import java.util.HashMap; ...
  • /*如果当前节点正好是第二个节点,那么则再次尝试获取*/ if (p == head && tryAcquire(arg)) { /*获取成功,*/ setHead(node); /*将当前节点设置为头结点*/ p.next = null; // help GC failed = ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 35,824
精华内容 14,329
关键字:

java独占锁和共享锁

java 订阅