1. 程式人生 > >java併發學習02---ReadWriteLock 讀寫鎖

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

同步器--讀寫鎖

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

之前我們無論是使用synchronized還是ReentrantLock,都是對整個操作進行了加鎖,但我們可以想象到,如果兩個執行緒都進行的知識讀取的操作,那麼實際上我們是不需要加鎖的。

而讀寫,包括寫與寫之間還是需要加鎖的。

而讀寫鎖就是幫我們來做這件事情的,如果連續兩次操作都是讀的話,那麼我們就不需要加鎖了

關於讀寫鎖的具體原理筆者能力有限,暫時還無法給出自己的理解,這裡給出一篇併發程式設計網的文章供大家參考

java中的讀寫鎖

 

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

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(); } } }

最後的執行結果:

執行緒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進入了執行緒共享資源修改之後: 709636739
Process finished with exit code 0