java併發學習02---ReadWriteLock 讀寫鎖

同步器--讀寫鎖java

java併發包中幫咱們進行了一系列的封裝,以前的重入鎖須要咱們手動的加鎖和釋放鎖,而同步器只須要咱們簡單的去使用就能夠了。編程

以前咱們不管是使用synchronized仍是ReentrantLock,都是對整個操做進行了加鎖,但咱們能夠想象到,若是兩個線程都進行的知識讀取的操做,那麼實際上咱們是不須要加鎖的。api

而讀寫,包括寫與寫之間仍是須要加鎖的。併發

而讀寫鎖就是幫咱們來作這件事情的,若是連續兩次操做都是讀的話,那麼咱們就不須要加鎖了dom

關於讀寫鎖的具體原理筆者能力有限,暫時還沒法給出本身的理解,這裏給出一篇併發編程網的文章供你們參考ide

java中的讀寫鎖idea

 

這裏給出一個簡單的例子,說明讀寫鎖的使用:spa

package thread.thread_util;

import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 展現讀寫鎖的基本應用
 * 讀讀之間不加鎖
 * 讀寫和寫寫之間才加鎖
 */
public class Lesson18_ReadWriteLock {
    private static Lock lock = new ReentrantLock();
    private static ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private static Lock readLock = rwLock.readLock();
    private static Lock writeLock = rwLock.writeLock();
    private int value = 1;

    //模擬讀操做
    public void handleRead(Lock lock) throws InterruptedException{
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + "進入了線程\n");
            Thread.sleep(1000);
            System.out.println(value);
        } finally {
            lock.unlock();
        }

    }

    //模擬寫操做
    public void handleWrite(Lock lock, int index) throws InterruptedException{
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + "進入了線程");
            Thread.sleep(3000);
            value = index;
            System.out.println("共享資源修改以後: "+value);
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        final Lesson18_ReadWriteLock demo = new Lesson18_ReadWriteLock();

        //給讀線程加上讀鎖
        Runnable readTarget = new Runnable() {
            @Override
            public void run() {
                try {
                    demo.handleRead(readLock);
//                    demo.handleRead(lock);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        //給寫線程加上寫鎖
        Runnable writeTarget = new Runnable() {
            @Override
            public void run() {
                try {
                    demo.handleWrite(writeLock,new Random().nextInt());
//                    demo.handleWrite(lock,new Random().nextInt());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        for (int i = 0; i < 8 ; i++) {
            Thread thread = new Thread(readTarget);
            thread.setName("線程" + i);
            thread.start();
        }

        for (int i = 8; i < 10; i++) {
            Thread thread = new Thread(writeTarget);
            thread.setName("線程" + i);
            thread.start();
        }
    }
}

最後的運行結果:線程

code

線程0進入了線程

線程2進入了線程

線程3進入了線程

線程1進入了線程

線程7進入了線程

線程6進入了線程

線程5進入了線程

1
1
1
1
1
1
1
線程9進入了線程
共享資源修改以後: -1565636082
線程8進入了線程
共享資源修改以後: 641779894
線程4進入了線程

641779894

Process finished with exit code 0

線程8和線程9都是寫鎖鎖住的線程,因此當涉及到他們的時候,線程就會被阻塞

也就是說會在進入寫線程以前會停頓幾秒鐘,寫線程執行完以後再執行寫線程或者是讀線程也須要停頓幾秒鐘。

總結一下就是   讀 —— 寫,   寫 —— 讀 , 寫 —— 寫 之間都會進行阻塞。

而前面8個線程(0 ~ 7)則是一瞬間完成的,由於讀與讀之間是能夠並行的。

 

這裏本身的理解,根據代碼的執行結果,本身有一些理解,但不必定正確,詳細的原理你們仍是能夠去參考上面給出的那篇文章。

這裏的讀寫鎖的名稱是 ReentrantReadWriteLock ,它也是一種可重入的鎖,只不過以前的重入鎖是互斥的,只容許同一個線程重入,而讀寫鎖也是重入的,但它是容許兩個連續的讀線程重入。

 

關於讀寫鎖就小結到這裏了。

 

"C:\Program Files\Java\jdk1.8.0_161\bin\java.exe" "-javaagent:D:\program files\IntelliJ IDEA 2018.1.2\lib\idea_rt.jar=45972:D:\program files\IntelliJ IDEA 2018.1.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;F:\codingfiles\learn\learn_java\javase\out\production\javase" thread.thread_util.Lesson18_ReadWriteLock線程1進入了線程線程0進入了線程線程4進入了線程線程2進入了線程線程3進入了線程線程7進入了線程線程10進入了線程線程8進入了線程線程13進入了線程線程11進入了線程線程6進入了線程線程5進入了線程線程9進入了線程線程15進入了線程線程16進入了線程線程12進入了線程線程14進入了線程線程17進入了線程111111111111111111線程18進入了線程共享資源修改以後: 22031275線程19進入了線程共享資源修改以後: 709636739Process finished with exit code 0

相關文章
相關標籤/搜索