ReentrantReadWriteLock详解

来源:互联网 发布:b超数据看男孩女孩 编辑:程序博客网 时间:2024/04/19 17:38
ReentrantLock具有完全互斥排他的效果,这样做虽然保证了示例变量的线程安全,但效率确实底下,所以JDK提供了一种读写锁ReentrantReadWriteLock类,使用它可以加快运行效率,在某些不需要操作实例变量的方法中,完全可以使用读写锁来提升运行效率。
一个资源能够被多个读线程访问,或者被一个写线程访问,但是不能同时存在读写线程。也就是说读写锁使用的场合是一个共享资源被大量读取操作,而只有少量的写操作(修改数据)。


①读读共享,读和读之间的锁可以共享

package com.dd;import java.util.concurrent.locks.ReentrantReadWriteLock;public class Service {private ReentrantReadWriteLock lock= new ReentrantReadWriteLock();public void read()  {try {lock.readLock().lock();System.out.println("threadName:"+Thread.currentThread().getName()+" start time:"+System.currentTimeMillis());Thread.sleep(1000);System.out.println("threadName:"+Thread.currentThread().getName()+" end time:"+System.currentTimeMillis());} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally {lock.readLock().unlock();}}}
package com.dd;public class ThreadA  extends Thread{private Service service;@Overridepublic void run() {// TODO Auto-generated method stubservice.read();}public ThreadA(Service service) {// TODO Auto-generated constructor stubthis.service = service;}}
package com.dd;public class ThreadB extends Thread{private Service service;@Overridepublic void run() {// TODO Auto-generated method stubservice.read();}public ThreadB(Service service) {// TODO Auto-generated constructor stubthis.service = service;}}
package com.dd;public class Run {public static void main(String[] args) {Service service = new Service();ThreadA ta = new ThreadA(service);ta.setName("A");ThreadB tb = new ThreadB(service);ta.start();tb.setName("B");tb.start();}}

运行结果:

threadName:B start time:1469174413695
threadName:A start time:1469174413695
threadName:B end time:1469174414709
threadName:A end time:1469174414709
从结果印证了读锁和读锁是可以共享的,
②写写互斥,写锁和写锁之间是互斥的

package com.xx;import java.util.concurrent.locks.ReentrantReadWriteLock;public class Service {private ReentrantReadWriteLock lock= new ReentrantReadWriteLock();public void write()  {try {lock.writeLock().lock();System.out.println("threadName:"+Thread.currentThread().getName()+" start time:"+System.currentTimeMillis());Thread.sleep(1000);System.out.println("threadName:"+Thread.currentThread().getName()+" end time:"+System.currentTimeMillis());} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally {lock.writeLock().unlock();}}}

package com.xx;public class ThreadA  extends Thread{private Service service;@Overridepublic void run() {// TODO Auto-generated method stubservice.write();}public ThreadA(Service service) {// TODO Auto-generated constructor stubthis.service = service;}}
package com.xx;public class ThreadB extends Thread{private Service service;@Overridepublic void run() {// TODO Auto-generated method stubservice.write();}public ThreadB(Service service) {// TODO Auto-generated constructor stubthis.service = service;}}
package com.xx;public class Run {public static void main(String[] args) {Service service = new Service();ThreadA ta = new ThreadA(service);ta.setName("A");ThreadB tb = new ThreadB(service);ta.start();tb.setName("B");tb.start();}}
打印结果:

threadName:A start time:1469174573400
threadName:A end time:1469174574414
threadName:B start time:1469174574414
threadName:B end time:1469174575429

从结果可以看出是顺序执行的,也就是写与写之间是互斥的

③读写、写读互斥

package com.dx;import java.util.concurrent.locks.ReentrantReadWriteLock;public class Service {private ReentrantReadWriteLock lock= new ReentrantReadWriteLock();public void write()  {try {lock.writeLock().lock();System.out.println("threadName:"+Thread.currentThread().getName()+" write start time:"+System.currentTimeMillis());Thread.sleep(10000);System.out.println("threadName:"+Thread.currentThread().getName()+" write end time:"+System.currentTimeMillis());} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally {lock.writeLock().unlock();}}public void read()  {try {lock.readLock().lock();System.out.println("threadName:"+Thread.currentThread().getName()+" read start time:"+System.currentTimeMillis());Thread.sleep(10000);System.out.println("threadName:"+Thread.currentThread().getName()+" read end time:"+System.currentTimeMillis());} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally {lock.readLock().unlock();}}}
package com.dx;public class ThreadA  extends Thread{private Service service;@Overridepublic void run() {// TODO Auto-generated method stubservice.read();}public ThreadA(Service service) {// TODO Auto-generated constructor stubthis.service = service;}}

package com.dx;public class ThreadB extends Thread{private Service service;@Overridepublic void run() {// TODO Auto-generated method stubservice.write();}public ThreadB(Service service) {// TODO Auto-generated constructor stubthis.service = service;}}
package com.dx;public class Run {public static void main(String[] args) {Service service = new Service();ThreadA ta = new ThreadA(service);ta.setName("A");ta.start();try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}ThreadB tb = new ThreadB(service);tb.setName("B");tb.start();}}

结果:

threadName:A read start time:1469174758914
threadName:A read end time:1469174768916
threadName:B write start time:1469174768916
threadName:B write end time:1469174778919

再将Run.java 改为

package com.dx;public class Run {public static void main(String[] args) {Service service = new Service();ThreadB tb = new ThreadB(service);tb.setName("B");tb.start();try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}ThreadA ta = new ThreadA(service);ta.setName("A");ta.start();}}

打印结果:

threadName:B write start time:1469174815988
threadName:B write end time:1469174826001
threadName:A read start time:1469174826014
threadName:A read end time:1469174836029

可以看出不管是读写,还是写读都是互斥的




0 0