這篇文章主要介紹了Java並發編程之重入鎖與讀寫鎖,文中相關實例代碼詳細,測試可用,具有一定參考價值,需要的朋友可以了解下。
重入鎖定
重入鎖,顧名思義,就是支援重進入的鎖,它表示該鎖定能夠支援一個執行緒對資源的重複加鎖。重進入是指任意執行緒在取得到鎖定之後能夠再次取得該鎖定而不會被鎖定阻塞,該特性的實作需要解決以下兩個問題。
1、執行緒再次取得鎖定。鎖需要去識別獲取鎖的線程是否為當前佔據鎖的線程,如果是,則再次成功獲取。
2、鎖的最終釋放。線程重複n次獲取了鎖,隨後在第n次釋放該鎖後,其他線程能夠獲取到該鎖。鎖的最終釋放要求鎖定對於獲取進行計數自增,計數表示當前鎖被重複獲取的次數,而鎖被釋放時,計數自減,當計數等於0時表示鎖已經成功釋放。
Java內內建鎖定(synchronize)和Lock(ReentrantLock)都是可重入的
synchronized 實例
package com.home; public class SynchronizedTest implements Runnable { public synchronized void method1() { System.out.println("method1获得锁,正常运行!"); method2(); } public synchronized void method2() { System.out.println("method2获得锁,也正常运行!"); } @Override public void run() { method1(); } public static void main(String[] args) { SynchronizedTest st = new SynchronizedTest(); new Thread(st).start(); new Thread(st).start(); } }
Lock 實例
package com.home; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockTest implements Runnable { Lock lock = new ReentrantLock(); public void method1() { lock.lock(); System.out.println("method1获得锁,正常运行!"); method2(); lock.unlock(); } public void method2() { lock.lock(); System.out.println("method2获得锁,也正常运行!"); lock.unlock(); } @Override public void run() { method1(); } public static void main(String[] args) { LockTest lt = new LockTest(); new Thread(lt).start(); new Thread(lt).start(); } }
兩個範例最後的結果都是正確的,結果如下:
method1获得锁,正常运行! method2获得锁,也正常运行! method1获得锁,正常运行! method2获得锁,也正常运行!
可重入鎖定最大的功能是避免死鎖
讀取寫入鎖定
讀寫鎖維護了一對相關的鎖,一個用於只讀操作,一個用於寫入操作。只要沒有writer,讀取鎖可以由多個reader執行緒同時保持。寫入鎖是獨佔的。
可重入讀寫鎖定ReentrantReadWriteLock
ReentrantReadWriteLock物件提供了readLock()和writeLock()方法, 用於取得讀取鎖定和寫入鎖定.
讀取鎖定允許多個reader執行緒同時持有, 而寫入鎖定最多只能有一個writter執行緒持有.
package com.home; import java.util.Random; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; class ReadWrte { // 共享数据,可以多个线程读数据,只能有一个线程写数据 private int data; // 创建读写锁 ReadWriteLock rwLock = new ReentrantReadWriteLock(); /** * 读数据,上读锁 */ public void get() { // 读锁 rwLock.readLock().lock(); try { System.out.println(Thread.currentThread().getName() + ",Read!"); Thread.sleep((long) Math.random() * 1000); System.out.println(Thread.currentThread().getName() + " 读出的数据为:" + this.getData()); } catch (Exception e) { e.printStackTrace(); } finally { rwLock.readLock().unlock(); } } /** * 写数据,上写锁 * * @param data */ public void put(int data) { // 写锁 rwLock.writeLock().lock(); try { System.out.println(Thread.currentThread().getName() + ",Write!"); Thread.sleep((long) Math.random() * 1000); this.setData(data); System.out.println(Thread.currentThread().getName() + " 写入的数据为:" + this.getData()); } catch (InterruptedException e) { e.printStackTrace(); } finally { rwLock.writeLock().unlock(); } } public int getData() { return data; } public void setData(int data) { this.data = data; } } /** * 测试类 * * @author itmyhome * */ public class ReadWriteLockTest { /** * @param args */ public static void main(String[] args) { // 创建ReadWrte对象 final ReadWrte rw = new ReadWrte(); for (int i = 0; i < 10; i++) { // 创建并启动10个读线程 new Thread(new Runnable() { @Override public void run() { rw.get(); } }).start(); // 创建并启动10个写线程 new Thread(new Runnable() { @Override public void run() { // 写入一个随机数 rw.put(new Random().nextInt(8)); } }).start(); } } }輸出為
Thread-0,Read! Thread-4,Read! Thread-8,Read! Thread-12,Read! Thread-0 读出的数据为:0 Thread-4 读出的数据为:0 Thread-8 读出的数据为:0 Thread-12 读出的数据为:0 Thread-19,Write! Thread-19 写入的数据为:5 Thread-7,Write! Thread-7 写入的数据为:7 Thread-3,Write! Thread-3 写入的数据为:4 Thread-16,Read! Thread-16 读出的数据为:4 Thread-11,Write! Thread-11 写入的数据为:0 Thread-15,Write! Thread-15 写入的数据为:5 Thread-2,Read! Thread-2 读出的数据为:5 Thread-17,Write! Thread-17 写入的数据为:2 Thread-6,Read! Thread-6 读出的数据为:2 Thread-1,Write! Thread-1 写入的数据为:5 Thread-13,Write! Thread-13 写入的数据为:4 Thread-9,Write! Thread-9 写入的数据为:7 Thread-5,Write! Thread-5 写入的数据为:2 Thread-10,Read! Thread-10 读出的数据为:2 Thread-18,Read! Thread-14,Read! Thread-18 读出的数据为:2 Thread-14 读出的数据为:2從圖中我們可以看出,可以多個執行緒同時讀,但只能一個執行緒寫,即寫資料和寫入資料一併完成。
總結#
以上是Java並發關於重入鎖與讀寫鎖的詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!