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
    

      读写操作也是互斥的。

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

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

      

  • 相关阅读:
    ASP.NET 页面间数据传递的方法
    ASP.NET中实现页面间数据传递的方法
    C# 连接SQL数据库
    C# 通过url地址获取页面内容
    JS弹窗带遮蔽的功能
    C# Code First 实例学习
    CS窗体程序数据列表分页
    关于RDLC报表打印预览界面显示页码问号的问题
    C#Dictionary键值对取值用法
    分别获取一个字符串中的字母和数字
  • 原文地址:https://www.cnblogs.com/hrlizhi/p/9498056.html
Copyright © 2011-2022 走看看