读《图解java多线程设计模式》总结--Read-write Lock

1,从名字上看就是一种比较特殊的锁,该锁能针对读和写操作分别对读线程和写线程进行不同的处理,确保不会出现冲突情况

2,适用范围,对于共享资源,如果两个线程同时进行读操作是不会发生任何冲突的,因为读操作不会修改共享资源的值。但如果一个线程在读,另外一个线程在写,或者两个线程同时进行写操作,那么就会发生冲突,Read-write Lock模式就是用于这种场景下,一方面同时读不加锁提高性能,另一方面防止出现读写或写写冲突。

3,实现方式,这里有4个概念,Reader进行读操作的线程,Writer进行写操作线程,SharedResouce共享资源,ReadWriteLock读写锁,其中ReadWriteLock是核心,他增加了3个变量,分别是正在进行读的线程数,正在进行写操作的线程数,等待进行写操作的线程数,利用这3个变量来控制当前线程在请求锁的时候是否需要等待。

4,代码实现

1)定义读写锁类,具体看代码注解

 

package readwritelock.study;

public class ReadWriteLock {

    public int  readingThreadNum=0;  //实际正在进行读操作的线程数
    public int writingThreadNum=0;   //实际正在进行写操作的线程数
    public int waitingWriteThreadNum=0; //正在等待写入操作的线程数

    public  synchronized  void readLock()
    {
        //存在着正在进行写操作或有线程等待申请写锁,此时不能申请读锁
        while (writingThreadNum>0||waitingWriteThreadNum>0) {  
            try {
                System.out.println("Thread name:"+Thread.currentThread().getName()+" waiting to  get readLock ");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("Thread name:"+Thread.currentThread().getName()+" get readLock ");
        readingThreadNum++;
    }

    //释放写锁
    public synchronized  void readUnlock()
    {
       
        readingThreadNum--;
        System.out.println("Thread name:"+Thread.currentThread().getName()+" release readLock ");
        notifyAll();
    }

    public synchronized  void writeLock()
    {
        waitingWriteThreadNum++;
        try {
            //存在着正在进行读操作的线程或者正在进行写操作的线程,此时不能申请写锁
            while (readingThreadNum > 0 || writingThreadNum > 0) {

                System.out.println("Thread name:"+Thread.currentThread().getName()+" waiting to  get writeLock ");
                wait();
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }finally {
            waitingWriteThreadNum--;
        }
        System.out.println("Thread name:"+Thread.currentThread().getName()+" get writeLock ");
        writingThreadNum++;
    }
    
   //释放写锁
    public synchronized  void writeUnlock()
    {
        writingThreadNum--;
        System.out.println("Thread name:"+Thread.currentThread().getName()+" release wirteLock ");
        notifyAll();
    }
}

 

2)定义共享资源类,利用读写锁控制读写操作

 

package readwritelock.study;

public class SharedResource {

    private String resource="Resource1";
    ReadWriteLock readWriteLock=new ReadWriteLock();

    public void read()
    {
        readWriteLock.readLock();
        System.out.println("Thread name:"+Thread.currentThread().getName()+" read shared resource:"+ resource);
        readWriteLock.readUnlock();
    }

    public void wirte(String newResource)
    {
        readWriteLock.writeLock();
        resource=newResource;
        System.out.println("Thread name:"+Thread.currentThread().getName()+" set shared resource:"+ resource);
        readWriteLock.writeUnlock();
    }
}

3)开启4条线程,分别2条读线程,2条写线程,读线程进行2次读操作,写线程进行1次写操作

package readwritelock.study;

import java.util.Random;

public class ReadWirteLockTest {

    public static void main(String[] args) {
        SharedResource sharedResource=new SharedResource();

        Thread read1=new Thread(
                new Runnable() {
                    @Override
                    public void run() {
                        Random random=new Random(8);
                        for(int i=0;i<2;i++) {
                            try {
                                sharedResource.read();
                                Thread.sleep(random.nextInt(100));//随机降低线程执行速度
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
        );



        Thread read2=new Thread(
                new Runnable() {
                    @Override
                    public void run() {
                        Random random=new Random(8);
                        for(int i=0;i<2;i++) {
                            try {
                                sharedResource.read();
                                Thread.sleep(random.nextInt(100));//随机降低线程执行速度
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
        );

        Thread write1=new Thread(
                new Runnable() {
                    @Override
                    public void run() {
                        Random random=new Random(5);
                        for(int i=0;i<1;i++) {
                            try {
                                sharedResource.wirte("write thread1_"+i);
                                Thread.sleep(random.nextInt(100));//随机降低线程执行速度
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
        );

        Thread write2=new Thread(
                new Runnable() {
                    @Override
                    public void run() {
                        Random random=new Random(5);
                        for(int i=0;i<1;i++) {
                            try {
                                sharedResource.wirte("write thread2_"+i);
                                Thread.sleep(random.nextInt(100));//随机降低线程执行速度
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
        );

        read1.start();
        read2.start();
        write1.start();
        write2.start();
    }
}

4) 运行结果

 

Thread name:Thread-1 get readLock    //线程1获取到读锁
Thread name:Thread-2 waiting to  get writeLock    //由于存在读操作,线程2不能获取到写锁只能等待
Thread name:Thread-1 read shared resource:Resource1  //线程1读取共享资源值
Thread name:Thread-3 waiting to  get writeLock    //由于存在读操作,线程3不能获取到写锁只能等待
Thread name:Thread-0 waiting to  get readLock    //由于存在等待进行读操作,线程0不能获取到读锁只能等待
Thread name:Thread-1 release readLock     //线程1释放读锁,此时没有任何读操作进行, readingThreadNum=0
Thread name:Thread-0 waiting to  get readLock    //由于存在等待进行读操作,线程0不能获取到读锁只能等待
Thread name:Thread-3 get writeLock     //此时没有任何读操作进行,也没有任何写操作进行,线程3获取到写锁
Thread name:Thread-3 set shared resource:write thread2_0  //线程3修改共享资源值
Thread name:Thread-2 waiting to  get writeLock    //由于线程3进行写操作,线程2不能获取到写锁只能等待
Thread name:Thread-3 release wirteLock   //线程3释放写锁   writingThreadNum=0
Thread name:Thread-2 get writeLock   //不存在任何读写操作,线程2获取的到写锁
Thread name:Thread-2 set shared resource:write thread1_0  //线程2修改共享资源值
Thread name:Thread-0 waiting to  get readLock   //线程2进行写操作,线程0获取不到读锁
Thread name:Thread-2 release wirteLock   //线程2释放写锁   writingThreadNum=0
Thread name:Thread-0 get readLock   //不存在任何读写操作,线程0获取的到读锁
Thread name:Thread-0 read shared resource:write thread1_0  //线程0读取共享资源值
Thread name:Thread-0 release readLock    //线程0释放读锁
Thread name:Thread-1 get readLock   //线程1获取的到读锁
Thread name:Thread-1 read shared resource:write thread1_0   //线程1读取共享资源值
Thread name:Thread-0 get readLock    //线程0获取的到读锁 ,同时读不冲突
Thread name:Thread-0 read shared resource:write thread1_0  //线程0读取共享资源值
Thread name:Thread-1 release readLock   //线程1释放读锁
Thread name:Thread-0 release readLock   //线程0释放读锁

你可能感兴趣的:(40程序员,补学java多线程)