讀寫鎖ReentrantReadWriteLock:讀讀共享,讀寫互斥,寫寫互斥

介紹

DK1.5以後,提供了讀寫鎖ReentrantReadWriteLock,讀寫鎖維護了一對鎖:一個讀鎖,一個寫鎖。經過分離讀鎖和寫鎖,使得併發性相比通常的排他鎖有了很大提高。在讀多寫少的狀況下,讀寫鎖可以提供比排他鎖更好的併發性和吞吐量。java

源碼定義

/* 
* <p>This lock supports a maximum of 65535 recursive write locks
 * and 65535 read locks. Attempts to exceed these limits result in
 * {@link Error} throws from locking methods.
 *
 * @since 1.5
 * @author Doug Lea
 */
public class ReentrantReadWriteLock
        implements ReadWriteLock, java.io.Serializable {
    private static final long serialVersionUID = -6992448646407690164L;
    /** Inner class providing readlock */
    private final ReentrantReadWriteLock.ReadLock readerLock;
    /** Inner class providing writelock */
    private final ReentrantReadWriteLock.WriteLock writerLock;
    /** Performs all synchronization mechanics */
    final Sync sync;
    ...
}

 

code

public class ReentrantReadWriteLockTest {
    ReentrantReadWriteLock lock;
    private ReentrantReadWriteLock.ReadLock readLock;
    private ReentrantReadWriteLock.WriteLock writeLock;

    private ReentrantReadWriteLockTest() {
        lock = new ReentrantReadWriteLock();
        readLock = lock.readLock();
        writeLock = lock.writeLock();
    }

    public void read() {
        try {
            readLock.lock();
            System.out.println(Thread.currentThread().getName() + " 開始讀了。。。");
            Thread.sleep(3000);
        }catch (InterruptedException e) {

        }finally {
            System.out.println(Thread.currentThread().getName() + " 讀結束了。。。");
            readLock.unlock();
        }
    }

    public void write() {
        try {
            writeLock.lock();
            System.out.println(Thread.currentThread().getName() + " 開始寫了。。。");
            Thread.sleep(3000);
        } catch (InterruptedException e) {

        } finally {
            System.out.println(Thread.currentThread().getName() + " 寫完了。。。");
            writeLock.unlock();
        }
} }

測試1併發

 public static void main(String[] args) {
        final ReentrantReadWriteLockTest test = new ReentrantReadWriteLockTest();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                test.read();

            }
        }, "ReadThread1");
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                test.read();
            }
        }, "ReadThread2");
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                test.write();
            }
        }, "WriteThread1");
        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                test.write();
            }
        }, "WriteThread4");

        t1.start();
        t2.start();
    }

輸出ide

ReadThread1 開始讀了。。。
ReadThread2 開始讀了。。。
ReadThread1 讀結束了。。。
ReadThread2 讀結束了。。。

結論:讀讀共享  測試

測試2spa

t2.start();
t3.start();

輸出code

ReadThread2 開始讀了。。。
ReadThread2 讀結束了。。。
WriteThread1 開始寫了。。。
WriteThread1 寫完了。。。

結論:讀寫互斥orm

測試3blog

t4.start();
t3.start();

輸出get

WriteThread4 開始寫了。。。
WriteThread4 寫完了。。。
WriteThread1 開始寫了。。。
WriteThread1 寫完了。。。

結論:寫寫互斥源碼

注意:新生成變量時,要用final修飾

final ReentrantReadWriteLockTest test = new ReentrantReadWriteLockTest();

緣由:從內部類訪問本地變量,本地變量要被聲明爲final類型

相關文章
相關標籤/搜索