同步器--讀寫鎖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