1. 程式人生 > >java中的互斥鎖,訊號量和多執行緒等待機制

java中的互斥鎖,訊號量和多執行緒等待機制

互斥鎖和訊號量都是作業系統中為併發程式設計設計基本概念,互斥鎖和訊號量的概念上的不同在於,對於同一個資源,互斥鎖只有0和1 的概念,而訊號量不止於此。也就是說,訊號量可以使資源同時被多個執行緒訪問,而互斥鎖同時只能被一個執行緒訪問

互斥鎖在java中的實現就是 ReetranLock , 在訪問一個同步資源時,它的物件需要通過方法 tryLock() 獲得這個鎖,如果失敗,返回 false,成功返回true。根據返回的資訊來判斷是否要訪問這個被同步的資源。看下面的例子

public class ReentranLockExample {
    private static int count = 0;
    private static ReentrantLock reentrantLock = new ReentrantLock();
    static class MyThread extends Thread{

        @Override
        public void run() {
            super.run();
            try {
                while (true){
                    boolean result = reentrantLock.tryLock();
                    if (result){
                        System.out.println(Thread.currentThread().getName() + "get the lock success and run the syn code " + count ++);
                        reentrantLock.unlock();
                    }else{
                        System.out.println(Thread.currentThread().getName() + "get the lock failed and run the syn code " + count);
                    }
                    System.out.println(Thread.currentThread().getName() + "run the asyntronized code  " + count);
                    Thread.sleep(500);
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args){
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
        thread1.start();
        thread2.start();
    }

}

訊號量相當於一個計數器,如果執行緒想要訪問某個資源,則先要獲得這個資源的訊號量,並且訊號量內部的計數器減1 ,訊號量內部的計數器大於0則意味著有可以使用的資源,當執行緒使用完某個資源時,必須釋放這個資源的訊號量。訊號量的一個作用就是可以實現指定個執行緒去同事訪問某個資源。只需要在初始化 。 

訊號量在 Java中的實現是 Semaphore  ,其在初始化時傳入一個整型數, 用來指定同步資源最大的併發訪問量

public class SemaphoreExample {
    private static Semaphore semaphore = new Semaphore(2);
    private String lock = "lock";
    private static int count = 0;
    static class MyThread extends Thread {

        @Override
        public void run() {
            super.run();
            try {
                while (true) {
                    semaphore.acquire();
                    Thread.sleep(500);
                    System.out.println(Thread.currentThread().getName() + "get the lock success and run the syn code " + count++);
                    semaphore.release();
                    Thread.sleep(500);
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args){
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
        MyThread thread3 = new MyThread();
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

 CountDownLatch 實現一個等待機制,在諸如 等待與會者到達後,開始會議的使用中。ConutDownLatch 在初始化中一個計數器,用來指定需要等待的個數。在併發程式設計中,所解決的需求就是,等待所有的執行緒到達某個點後。才開始進行下一步,有點類似於開會,只有當所有的與會人員都到齊後,會議才能開始
public class CountDownLatchExample {
    private static CountDownLatch mCountDownLatch = new CountDownLatch(3);
    static class MyThread extends Thread {
        int awaitTime;
        public MyThread(int i) {
            this.awaitTime = i;
        }

        @Override
        public void run() {
            super.run();
            try {
                while (true) {
                    Thread.sleep(awaitTime);
                    System.out.println(Thread.currentThread().getName() + "arrived " );
                    mCountDownLatch.countDown();
                    mCountDownLatch.await(); //可以指定等待時間
                    System.out.println(Thread.currentThread().getName() + "start meeting " );
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args){
        MyThread thread1 = new MyThread(500);
        MyThread thread2 = new MyThread(1000);
        MyThread thread3 = new MyThread(2000);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}