第四章-java多線程核心技術-Lock鎖-第三篇

Condition實現順序運行

使用condition對象能夠對線程業務進行規劃和排序。請看以下代碼java

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Run {
    volatile private static int nextPrintWho = 1;
    private static ReentrantLock lock = new ReentrantLock();
    final private static Condition conditionA = lock.newCondition();
    final private static Condition conditionB = lock.newCondition();
    final private static Condition conditionC = lock.newCondition();

    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                super.run();
                try {
                    lock.lock();
                    while (nextPrintWho != 1) {
                        conditionA.await();
                    }

                    for (int i = 0; i < 3; i++) {
                        System.out.println("printA is " + i);
                    }
                    nextPrintWho = 2;
                    conditionB.signalAll();
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };

        Thread threadb = new Thread() {
            @Override
            public void run() {
                super.run();
                try {
                    lock.lock();
                    while (nextPrintWho != 2) {
                        conditionB.await();
                    }

                    for (int i = 0; i < 3; i++) {
                        System.out.println("printB is " + i);
                    }
                    nextPrintWho = 3;
                    conditionC.signalAll();
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };

        Thread threadc = new Thread() {
            @Override
            public void run() {
                super.run();
                try {
                    lock.lock();
                    while (nextPrintWho != 3) {
                        conditionC.await();
                    }

                    for (int i = 0; i < 3; i++) {
                        System.out.println("printC is " + i);
                    }
                    nextPrintWho = 1;
                    conditionB.signalAll();
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };
        Thread[] aArray = new Thread[10];
        Thread[] bArray = new Thread[10];
        Thread[] cArray = new Thread[10];

        for (int i =0 ;i <5 ;i++) {
            aArray[i] = new Thread(thread);
            bArray[i] = new Thread(threadb);
            cArray[i] = new Thread(threadc);
            aArray[i].start();
            bArray[i].start();
            cArray[i].start();
        }
    }
}

輸出結果安全

printA is 0
printA is 1
printA is 2
printB is 0
printB is 1
printB is 2
printC is 0
printC is 1
printC is 2
printA is 0
printA is 1
printA is 2
printB is 0
printB is 1
printB is 2
printC is 0
printC is 1
printC is 2
printA is 0
printA is 1
printA is 2
printB is 0
printB is 1
printB is 2
printC is 0
printC is 1
printC is 2

讀寫鎖的產生

ReentrantLock鎖是徹底互斥的鎖,即同一時間內只有一個線程執行鎖後面的方法,這樣作雖然保證了變量的線程安全性,可是效果是很是低下的。因此jdk提供了一種讀寫鎖,在某些不須要操做gong共享變量的狀況下徹底能夠使用讀寫鎖來提高方法的運行速度。ide

讀寫鎖包含了兩個鎖,一個是讀鎖,也稱共享鎖,一個是寫鎖,也稱排他鎖。即多個讀鎖之間不互斥,寫鎖和讀鎖互斥,讀鎖和讀鎖互斥。在沒有線程執行寫入操做的時候,進行讀取操做的多個線程均可以獲取讀鎖,寫鎖只有在得到鎖後才能進行寫操做。this

讀讀共享

請看以下代碼線程

public class ReadLock {
    private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    public void read() {
        try {
            readWriteLock.readLock().lock();
            System.out.println("得到鎖---->線程名稱是---->"+Thread.currentThread().getName());
            Thread.sleep(1000);
            System.out.println("睡眠甦醒---->線程名稱是---->"+Thread.currentThread().getName());
        } catch (InterruptedException ex){
            ex.printStackTrace();
        }finally {
            readWriteLock.readLock().unlock();
        }
    }
}

public class ThreadA extends Thread{
    private  ReadLock readLock ;

    public ThreadA(ReadLock readLock) {
        this.readLock = readLock;
    }

    @Override
    public void run() {
        readLock.read();
    }
}


public class ThreadB extends Thread{
    private  ReadLock readLock ;

    public ThreadB(ReadLock readLock) {
        this.readLock = readLock;
    }

    @Override
    public void run() {
        readLock.read();
    }
}

public class Run {
    public static void main(String[] args) {
        ReadLock lock = new ReadLock();
        ThreadA threadA = new ThreadA(lock);
        threadA.setName("A");
        ThreadB threadB = new ThreadB(lock);
        threadB.setName("B");
        threadA.start();
        threadB.start();
    }
}

輸出結果是code

得到鎖---->線程名稱是---->B
得到鎖---->線程名稱是---->A
睡眠甦醒---->線程名稱是---->B
睡眠甦醒---->線程名稱是---->A

寫寫互斥

稍微修改上面的代碼對象

public class WriteLock {
    private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    public void read() {
        try {
            readWriteLock.writeLock().lock();
            System.out.println("得到鎖---->線程名稱是---->"+Thread.currentThread().getName());
            Thread.sleep(1000);
            System.out.println("睡眠甦醒---->線程名稱是---->"+Thread.currentThread().getName());
        } catch (InterruptedException ex){
            ex.printStackTrace();
        }finally {
            readWriteLock.writeLock().unlock();
        }
    }
}

輸出結果排序

得到鎖---->線程名稱是---->A
睡眠甦醒---->線程名稱是---->A
得到鎖---->線程名稱是---->B
睡眠甦醒---->線程名稱是---->B

讀寫互斥

請參考以下代碼get

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLock {
    private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    public void read() {
        try {
            readWriteLock.readLock().lock();
            System.out.println("讀線程得到鎖---->線程名稱是---->" + Thread.currentThread().getName());
            Thread.sleep(1000);
            System.out.println("讀線程睡眠甦醒---->線程名稱是---->" + Thread.currentThread().getName());
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        } finally {
            readWriteLock.readLock().unlock();
        }
    }

    public void write() {
        try {
            readWriteLock.writeLock().lock();
            System.out.println("寫線程得到鎖---->線程名稱是---->" + Thread.currentThread().getName());
            Thread.sleep(1000);
            System.out.println("寫線程睡眠甦醒---->線程名稱是---->" + Thread.currentThread().getName());
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }
}

public class ThreadA extends Thread{
    private ReadWriteLock readLock ;

    public ThreadA(ReadWriteLock readLock) {
        this.readLock = readLock;
    }

    @Override
    public void run() {
        readLock.read();
    }
}
public class ThreadB extends Thread{
    private ReadWriteLock readLock ;

    public ThreadB(ReadWriteLock readLock) {
        this.readLock = readLock;
    }

    @Override
    public void run() {
        readLock.write();
    }
}

public class Run {
    public static void main(String[] args) {
        ReadWriteLock lock = new ReadWriteLock();
        ThreadA threadA = new ThreadA(lock);
        threadA.setName("A");
        ThreadB threadB = new ThreadB(lock);
        threadB.setName("B");
        threadA.start();
        threadB.start();
    }
}

輸出結果it

讀線程得到鎖---->線程名稱是---->A
讀線程睡眠甦醒---->線程名稱是---->A
寫線程得到鎖---->線程名稱是---->B
寫線程睡眠甦醒---->線程名稱是---->B
相關文章
相關標籤/搜索