zoukankan      html  css  js  c++  java
  • 多线程程序设计学习(7)read-write lock pattern

    Read-Write Lock Pattern【读写】
    一:Read-Write Lock Pattern的参与者
    --->读写锁
    --->数据(共享资源)
    --->读线程
    --->写线程


           

    二Read-Write Lock Pattern模式什么时候使用
    --->
     * 为了多线线程环境下保护数据安全,我们必须避免的冲突
     * 一个线程读取,另一个线程写入的read-write conflick
     * 一个线程写入,另一个线程写入的write-write conflick
     * 一个线程读取,另一个线程也在读取不会产生冲突
     *
     * 当线程想要获取读取锁定时:
     * -->已经有线程在执行写入,则等待。不等待,则发生read-write conflick
     * -->已经有线程在读取,则不需要等待。不存在read-read conflick
     *
     * 当线程想要获取写入锁定时:
     * -->已经有线程在执行写入,则等待。不等待,则发生write-write conflick
     * -->已经有线程在执行读取,则等待。不等待,则发生read-write conflick


    --->利用同时(读取)不会引起数据冲突的特性,提高系统的性能
    --->适合读取操作繁重时
    --->适合读取操作比写入操作繁重时


    三:Read-Write Lock Pattern思考
    --->
    四进阶说明
    --->

    读写锁

     1 package com.yeepay.sxf.thread6;
     2 /**
     3  * 读写锁
     4  * @author sxf
     5  * 
     6  * 为了多线线程环境下保护数据安全,我们必须避免的冲突
     7  * 一个线程读取,另一个线程写入的read-write conflick
     8  * 一个线程写入,另一个线程写入的write-write conflick
     9  * 一个线程读取,另一个线程也在读取不会产生冲突
    10  * 
    11  * 当线程想要获取读取锁定时:
    12  *         -->已经有线程在执行写入,则等待。不等待,则发生read-write conflick
    13  *         -->已经有线程在读取,则不需要等待。不存在read-read conflick
    14  * 
    15  * 当线程想要获取写入锁定时:
    16  *         -->已经有线程在执行写入,则等待。不等待,则发生write-write conflick
    17  *         -->已经有线程在执行读取,则等待。不等待,则发生read-write conflick
    18  *
    19  */
    20 public class ReadWriteLock {
    21         //正在读取的线程个数
    22         private Integer readInteger=0;
    23         //正在写入的线程个数(最大值为1)
    24         private Integer writeInteger=0;
    25         //正在等待获取写入锁定的线程个数
    26         private Integer writeWaitInteger=0;
    27         //获取写入锁定优先的话,为true
    28         private boolean writeBoolean=false;
    29         
    30         //获取读取锁的方法
    31         public synchronized void readLock() throws InterruptedException{
    32             //如果有写入操作  ||写入优先并且存在等待写入的线程    则    读取线程等待
    33             while(writeInteger>0||(writeBoolean&&writeWaitInteger>0)){
    34                 wait();
    35             }
    36             //读取线程加1
    37             readInteger++;
    38         }
    39         //释放读取锁定的方法
    40         public synchronized void readUnLock(){
    41             //读取减一
    42             readInteger--;
    43             //将写入设置优先
    44             writeBoolean=true;
    45             //唤醒所有线程
    46             notifyAll();
    47         }
    48         
    49         //获取写入锁定
    50         public synchronized void writeLock() throws InterruptedException{
    51             //等待写入线程数量+1
    52             writeWaitInteger++;
    53             try {
    54                 //如果有读取线程或写入线程,则等待
    55                 while (readInteger>0||writeInteger>0) {
    56                     wait();
    57                 }
    58             }finally{
    59                 //执行到这,等待线程-1
    60                 writeWaitInteger--;
    61             }
    62             //写入线程数+1
    63             writeInteger++;
    64         }
    65         
    66         
    67         //释放写入锁定
    68         public synchronized void  writeUnLock(){
    69             //写入线程数-1
    70             writeInteger--;
    71             //写入的优先级去掉
    72             writeBoolean=false;
    73             //唤醒其他线程
    74             notifyAll();
    75         }
    76 
    77 }
    View Code

    数据类(公共资源)

     1 package com.yeepay.sxf.thread6;
     2 /**
     3  * 数据类
     4  * 持有公共数据+该公共数据的读写锁
     5  * @author sxf
     6  *
     7  */
     8 public class Data {
     9     //数据类持有的锁
    10     private final ReadWriteLock lock=new ReadWriteLock();
    11     //要访问的公共数据
    12     private final String[] buffer;
    13     //构造器
    14     public Data(int i){
    15         buffer=new String[i];
    16         for(int a=0;a<buffer.length;a++){
    17             buffer[a]="**";
    18         }
    19     }
    20     //读取数据的方法
    21     public  String[] read() throws InterruptedException{
    22         //获取读取锁定
    23         lock.readLock();
    24         try {
    25             //模拟读用了1秒
    26             Thread.sleep(1000);
    27             return doRead();
    28         } finally{
    29             //释放读取锁定
    30             lock.readUnLock();
    31         }
    32         
    33     }
    34     //真正的读取操作
    35     private String[] doRead(){
    36         return buffer;
    37     }
    38     
    39     //写入的操作
    40     public void write(String a) throws InterruptedException{
    41         //获取写入锁定
    42         lock.writeLock();
    43         try {
    44             //模拟写用了3秒
    45             Thread.sleep(1000);
    46             doWrite(a);
    47         }finally{
    48             //释放写入锁定
    49             lock.writeUnLock();
    50         }
    51 
    52     }
    53     
    54     //真正的写操作
    55     private void doWrite(String a){
    56         for(int i=0;i<buffer.length;i++){
    57             buffer[i]=a;
    58         }
    59     }
    60 
    61 }
    View Code

    读线程

     1 package com.yeepay.sxf.thread6;
     2 
     3 /**
     4  * 读线程
     5  * @author sxf
     6  *
     7  */
     8 public class ReadThread implements Runnable{
     9 
    10     private Data data;
    11     
    12     //构造器
    13     public ReadThread(Data data) {
    14         
    15         this.data=data;
    16     }
    17     @Override
    18     public void run() {
    19         while (true) {
    20                 try {
    21                     String [] aStrings=data.read();
    22                     System.out.println("["+Thread.currentThread().getName()+"] 读取数据为:"+aStrings[0]);
    23                 } catch (InterruptedException e) {
    24                     // TODO Auto-generated catch block
    25                     e.printStackTrace();
    26                 }
    27         }
    28         
    29     }
    30 
    31     
    32 }
    View Code

    写线程

     1 package com.yeepay.sxf.thread6;
     2 /**
     3  * 写线程
     4  *  * @author sxf
     5  *
     6  */
     7 public class WriteThead implements Runnable {
     8     //数据
     9     private Data data;
    10     
    11     //构造器
    12     public  WriteThead(Data data) {
    13         this.data=data;
    14     }
    15     
    16     @Override
    17     public void run() {
    18         
    19         while(true){
    20             for(int a=0;a<100;a++){
    21                 String name=Thread.currentThread().getName();
    22                 System.out.println("【"+name+"】写入"+a+"*"+name.substring(name.length()-2));
    23                 try {
    24                     data.write(a+"*"+name.substring(name.length()-2));
    25                 } catch (InterruptedException e) {
    26                     // TODO Auto-generated catch block
    27                     e.printStackTrace();
    28                 }
    29             }
    30         }
    31     }
    32     
    33 
    34 }
    View Code

    测试类

     1 package com.yeepay.sxf.thread6;
     2 /**
     3  * 测试类
     4  * @author sxf
     5  *
     6  */
     7 public class Test {
     8 
     9     public static void main(String[] args) {
    10         //声明公共数据类
    11         Data data=new Data(2);
    12         //声明读取线程
    13         Thread readThread1=new Thread(new ReadThread(data));
    14         readThread1.setName("读取线程sxf");
    15         Thread readThread2=new Thread(new ReadThread(data));
    16         readThread2.setName("读取线程sxs");
    17         Thread readThread3=new Thread(new ReadThread(data));
    18         readThread3.setName("读取线程sxy");
    19         
    20         //声明写入线程
    21         Thread writeThread1=new Thread(new WriteThead(data));
    22         writeThread1.setName("写入线程yk");
    23         Thread writeThread2=new Thread(new WriteThead(data));
    24         writeThread2.setName("写入线程shl");
    25         Thread writeThread3=new Thread(new WriteThead(data));
    26         writeThread3.setName("写入线程shj");
    27         
    28         //开启线程
    29         readThread1.start();
    30         readThread2.start();
    31         readThread3.start();
    32         
    33         writeThread1.start();
    34         writeThread2.start();
    35         writeThread3.start();
    36         
    37         
    38     }
    39 }
    View Code

    打印结果

    【写入线程yk】写入0*yk
    【写入线程shj】写入0*hj
    【写入线程shl】写入0*hl
    [读取线程sxf] 读取数据为:**
    [读取线程sxy] 读取数据为:**
    [读取线程sxs] 读取数据为:**
    【写入线程shj】写入1*hj
    [读取线程sxs] 读取数据为:0*hj
    [读取线程sxy] 读取数据为:0*hj
    [读取线程sxf] 读取数据为:0*hj
    【写入线程shj】写入2*hj
    [读取线程sxf] 读取数据为:1*hj
    [读取线程sxy] 读取数据为:1*hj
    [读取线程sxs] 读取数据为:1*hj
    【写入线程shl】写入1*hl
    【写入线程shj】写入3*hj
    【写入线程shl】写入2*hl
    【写入线程shj】写入4*hj
    【写入线程shl】写入3*hl
    【写入线程shj】写入5*hj
    【写入线程shl】写入4*hl

  • 相关阅读:
    SpringBoot入门学习(二)
    SpringBoot入门学习(一)
    eclipse调试程序界面简单介绍使用
    利用URLConnection来发送POST和GET请求
    查看用户所属的组
    linux下创建用户,给用户设置密码,给用户授权
    新linux系统上rz 与sz命令不可用
    pom.xml文件报错:web.xml is missing and <failOnMissingWebXml> is set to true
    MySql采用GROUP_CONCAT合并多条数据显示的方法
    Mysql计算时间差
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/4659883.html
Copyright © 2011-2022 走看看