• Android多线程研究(9)——读写锁


    一、什么是锁

    在Java的util.concurrent.locks包下有关于锁的接口和类如下:


    先看一段代码:

    package com.codeing.snail.test;
    
    
    public class ReadWriteLockTest {
    	public static void main(String[] args) {
    		final Output output = new Output();
    		new Thread(){
    			public void run() {
    				while(true){
    					output.output("CodeingSnail");
    				}
    			};
    		}.start();
    		
    		new Thread(){
    			public void run() {
    				while(true){
    					output.output("阳光小强");
    				}
    			};
    		}.start();
    	}
    	
    	static class Output{
    		public void output(String name){
    			char[] arry = name.toCharArray();
    			for(int i = 0; i < arry.length; i++){
    				System.out.print(arry[i]);
    			}
    			System.out.println();
    		}
    	}
    }

    输出的结果如下:

    如果我们想让“CodeingSnail"和“阳光小强"两个字符串都能完整输出,就需要使用synchronized关键字将输出部分声明,如下:

    		public synchronized void output(String name){
    			char[] arry = name.toCharArray();
    			for(int i = 0; i < arry.length; i++){
    				System.out.print(arry[i]);
    			}
    			System.out.println();
    		}

    其实,除了synchronized关键字之外,还可以使用锁(Lock)来实现同步。

    		ReentrantLock lock = new ReentrantLock();
    		public void output(String name){
    			lock.lock();
    			try{
    				char[] arry = name.toCharArray();
    				for(int i = 0; i < arry.length; i++){
    					System.out.print(arry[i]);
    				}
    				System.out.println();
    			}finally{
    				lock.unlock();
    			}
    		}
    上面代码使用try...finally语句块是为了防止出现异常执行不到unlock方法,ReentrantLock是Lock的实现类,Lock的作用和synchronized类似,但更加面向对象,要实现同步就必须使用同一个lock对象。

    二、什么是读写锁

    读写锁、分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥。下面我们来看一下API文档中的一个缓存器的例子:
    	class CachedData {
    		Object data;
    		volatile boolean cacheValid;
    		final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    
    		void processCachedData() {
    		     rwl.readLock().lock();
    		     if (!cacheValid) {
    		        // Must release read lock before acquiring write lock
    		        rwl.readLock().unlock();
    		        rwl.writeLock().lock();
    		        try {
    		          // Recheck state because another thread might have
    		          // acquired write lock and changed state before we did.
    		          if (!cacheValid) {
    		            data = ...
    		            cacheValid = true;
    		          }
    		          // Downgrade by acquiring read lock before releasing write lock
    		          rwl.readLock().lock();
    		        } finally {
    		          rwl.writeLock().unlock(); // Unlock write, still hold read
    		        }
    		     }
    
    		     try {
    		       use(data);
    		     } finally {
    		       rwl.readLock().unlock();
    		     }
    	     }
    	}
    假如有多个线程来读取数据,第一个线程进来先上一把写锁进行数据写入(先释放读锁),写入完成后将写锁降级为读锁(第15行),其他线程在读取数据的时候上读锁后互不影响。这样可以提高读取效率。



  • 相关阅读:
    ReentrantLock(重入锁)的源码解析
    vue项目使用vue-photo-preview插件实现点击图片放大预览和移动
    BOM简单总结
    js中属性类型:数据属性与访问器属性
    Javascript面向对象编程(三):非构造函数的继承(对象的深拷贝与浅拷贝)
    Javascript面向对象编程(二):构造函数的继承 作者:yuan一峰
    Javascript 面向对象编程(一):封装 作者:yuan一峰
    js面向对象、创建对象的工厂模式、构造函数模式、原型链模式
    Vue中父子组件执行的先后顺序
    Vue子组件调用父组件的方法
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6468794.html
Copyright © 2020-2023  润新知