java多線程編程(5)ReentrantReadWriteLock和ReentrantLock

前言

java中多線程編碼中除了synchronized 關鍵詞以外,就是使用lock接口實現鎖。本次就講一相關實現

ReentrantLock

ReentrantLock的第一個例子可以簡單的用於一個鎖。鎖定一個變量,只有當線程獲得鎖的時候纔可以對變量進行修改。下面的代碼舉例的了我鎖住了一個靜態變量。即使多線程修改,也不會出現多線程問題。相反如果去掉鎖,會發現變量的修改會出現多線程問題

import java.util.concurrent.locks.ReentrantLock;

public class Test20 extends Thread{

    public static int result = 0;
    public static class Test extends Thread{
        private ReentrantLock lock;
        public Test(ReentrantLock lock) {
            this.lock = lock;
        }

        public void run(){
            while (true){
            	//可以去除lock和unlock發現發生了線程不安全
                lock.lock();
                result++;
                System.out.println("thread"+Thread.currentThread().getName()+",result"+result);
                lock.unlock();
            }
        }


    }
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock(true);
        Test test1 = new Test(lock);
        Test test2 = new Test(lock);
        Test test3 = new Test(lock);
        test1.setName("test1");
        test2.setName("test2");
        test3.setName("test3");
        test1.start();
        test2.start();
        test3.start();
    }
}

trylock()可以在一段時間內獲得一個鎖,可以看到獲得鎖的線程begin了,然後看到try失敗的線程也迅速進入,進行了begin。表明trylock()成功了。

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

public class Test21 extends Thread{
    private ReentrantLock lock;
    public Test21(ReentrantLock lock) {
        this.lock = lock;
    }

    public void run(){
        while (true){
            boolean locked = false;
            try {

                locked = lock.tryLock(1000, TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("thread"+Thread.currentThread().getName()+"begin");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("thread"+Thread.currentThread().getName()+"next");
            if(locked){
                lock.unlock();
            }

        }
    }

    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock(true);
        Test21 test1 = new Test21(lock);
        Test21 test2 = new Test21(lock);
        Test21 test3 = new Test21(lock);
        test1.setName("test1");
        test2.setName("test2");
        test3.setName("test3");
        test1.start();
        test2.start();
        test3.start();
    }
}

ReentrantReadWriteLock

可以看到寫了2個類,一個進行寫,一個進行讀,可以看到每次讀線程都會同時進行,寫線程是單獨進行的。交替進行,在寫線程進行寫的時候會卡住讀線程的相關操作,但是讀線程是可以併發進行的。各個讀之間不受影響

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Test22 extends Thread{
    public static int result = 0;
    static class Test22A extends Thread{
        private ReentrantReadWriteLock lock;
        public Test22A(ReentrantReadWriteLock lock) {
            this.lock = lock;
        }

        public void run(){
            while (true){
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                lock.writeLock().lock();
                System.out.println("result change");
                result = result+1;
                System.out.println("thread:"+Thread.currentThread().getName()+",result:"+result);
                lock.writeLock().unlock();
            }

        }
    }
    static class Test22B extends Thread {
        private ReentrantReadWriteLock lock;

        public Test22B(ReentrantReadWriteLock lock) {
            this.lock = lock;
        }

        public void run() {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                lock.readLock().lock();
                System.out.println("thread:" + Thread.currentThread().getName() + ",result:" + result);
                lock.readLock().unlock();
            }
        }
    }

    public static void main(String[] args) {
        ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
        Test22B b1 = new Test22B(lock);
        Test22B b2 = new Test22B(lock);
        Test22B b3 = new Test22B(lock);
        Test22B b4 = new Test22B(lock);

        Test22A a1 = new Test22A(lock);
        Test22A a2 = new Test22A(lock);
        b1.setName("b1");
        b2.setName("b2");
        b3.setName("b3");
        b4.setName("b4");
        a1.setName("a1");
        a2.setName("a2");
        a1.start();
        a2.start();
        b1.start();
        b2.start();
        b3.start();
        b4.start();
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章