zoukankan      html  css  js  c++  java
  • 多线程学习 读写锁

      类ReentranLock具有万川互斥排他的效果,即同一时间只有一个线程在执行ReentrantLock.lock()方法后面的任务。这样虽然保证了实例变量的线程安全性,

    但效率却是非常低下的。所以在jdk中提供了一种读写锁ReentrantReadWriteLock类,使它可以加快运行效率,在某些不需要操作实例变量的方法中,完全可以使用读写锁

    ReentrantReadWriteLock来提升该方法的代码运行速度。

      读写锁表示也有两个锁,一个是读操作相关的锁,也称为共享锁;另一个事写操作相关的做,也叫排他锁。也就是多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。

    在没有现成Thread进行写入操作时,进行读取操作的多个Thread都可以获取读锁,而进行写入操作的Thread只有在获取写锁后才能进行写入操作。即多个Thread可以同时进行读取操作,但是同一时刻,只允许一个Thread进行写入操作

      读读共享:

      Service类:

      

    package ReadAndWriteLock;
    
    import java.io.BufferedWriter;
    import java.time.LocalDate;
    import java.util.concurrent.locks.ReentrantLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    public class Service {
    
    	private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
    	
    	public void read(){
    		try {
    			try {
    				lock.readLock().lock();;
    				System.out.println("线程 : "+Thread.currentThread().getName()+"  时间: "+System.currentTimeMillis()+"  获得锁");
    				Thread.sleep(10000);
    			} finally {
    				lock.readLock().unlock();
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    

      主方法:

    package ReadAndWriteLock;
    
    public class Run {
    
    		public static void main(String[] args) {
    			final Service service=new Service();
    			
    			new Thread(new Runnable() {
    				public void run() {
    					service.read();
    				}
    			}).start();
    			
    			new Thread(new Runnable() {
    				public void run() {
    					service.read();
    				}
    			}).start();
    		}
    	
    }
    

      控制台:

    线程 : Thread-0  时间: 1534585340658  获得锁
    线程 : Thread-1  时间: 1534585340659  获得锁
    

      可以发现,两个线程几乎同时进入了lock方法后面的代码,说明在此使用读写锁可以提供程序运行效率,允许多个线程同时制定lock()方法后面的代码。

      写写互斥:

      Service类

    public class Service1 {
    
    	private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
    	
    	public void write() {
    		try {
    			try {
    				lock.writeLock().lock();;
    				System.out.println("线程:  "+Thread.currentThread().getName()+" 时间:  "+System.currentTimeMillis()+"  获得锁");
    				Thread.sleep(10000);
    			} finally {
    				lock.writeLock().unlock();
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	
    }
    

      主线程:

    public class Run {
    
    		public static void main(String[] args) {
    			final Service1 service1=new Service1();
    			
    			new Thread(new Runnable() {
    				public void run() {
    					service1.write();
    				}
    			}).start();
    			
    			new Thread(new Runnable() {
    				public void run() {
    					service1.write();
    				}
    			}).start();
    		}
    	
    }
    

      控制台:

    线程:  Thread-0 时间:  1534585587952  获得锁
    线程:  Thread-1 时间:  1534585597955  获得锁
    

      使用写锁代码lock.writeLock()的效果就是同意时间只允许一个线程执行lock()方法后面的代码。

       写读互斥:

      service2类

    public class Service2 {
    
    	private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
    	
    	public void read() {
    		try {
    			try {
    				lock.readLock().lock();
    				System.out.println("线程: "+Thread.currentThread().getName()+"  时间: "+System.currentTimeMillis());
    				Thread.sleep(10000);
    			} finally {
    				lock.readLock().unlock();
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public void write() {
    		try {
    			try {
    				lock.writeLock().lock();
    				System.out.println("线程: "+Thread.currentThread().getName()+"  时间: "+System.currentTimeMillis());
    				Thread.sleep(10000);
    			} finally {
    				lock.writeLock().unlock();
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    

      主线程:

    public class Run {
    
    		public static void main(String[] args) {
    			final Service2 service2=new Service2();
    			
    			new Thread(new Runnable() {
    				public void run() {
    					service2.write();
    				}
    			}).start();
    			
    			new Thread(new Runnable() {
    				public void run() {
    					service2.read();
    				}
    			}).start();
    		}
    	
    }
    

      控制台:

    线程: Thread-0  时间: 1534586198910
    线程: Thread-1  时间: 1534586208910
    

      从时间上看,写读操作是互斥的。

      读写互斥:

      将主线程中的方法改为如下:

    public class Run {
    
    		public static void main(String[] args) throws InterruptedException {
    			final Service2 service2=new Service2();
    			
    			new Thread(new Runnable() {
    				public void run() {
    					service2.read();
    				}
    			}).start();
    			Thread.sleep(1000);
    			new Thread(new Runnable() {
    				public void run() {
    					service2.write();
    				}
    			}).start();
    		}
    	
    }
    

      控制台:

    线程: Thread-0  时间: 1534586426809
    线程: Thread-1  时间: 1534586436810
    

      读写操作也是互斥的。

      结论: 读写,写读,写写都是互斥的:而读读是异步的,非互斥的。

      每一个优秀的人,都有一段沉默的时光。不抱怨,不诉苦,最后度过那段感动自己的日子。

      

  • 相关阅读:
    山东财经大学新生赛暨天梯赛选拔赛 A 骆驼拼写法
    Code 墓地 问题 A: 看电视(区间贪心)
    第九届蓝桥杯 乘积尾零(Java大数)
    《真正的力量来自内心深处》
    蓝桥杯训练 历届试题 买不到的数目 (猜公式)
    前缀和与差分 算法详解
    蓝桥杯训练 历届试题 回文数字 (暴力求解,毫无任何技术含量)
    蓝桥杯训练 历届试题 最大子阵 (只用了前缀和,没用dp写)
    实习开始
    MVC缺点总结
  • 原文地址:https://www.cnblogs.com/hrlizhi/p/9498056.html
Copyright © 2011-2022 走看看