(二)線程同步_4---使用Lock同步代碼塊

使用Lock同步代碼塊

Java提供了另一種機制去同步代碼塊,這種機制比synchronized關鍵字更加靈活也更增強大,這種機制就是基於Lock接口和相關的實現類(如ReentrantLock),這種機制有已下幾個優勢:java

它使得同步代碼塊可以能夠以更加靈活的方式組織;使用synchronized關鍵字將會不得不放棄以更加靈活的結構組織方式處理同步代碼塊,而Lock接口可使咱們可以充分利用這種優點;dom

  • Lock接口相比synchronized關鍵字提供了更多的功能,好比tryLock(),這個方法被其它線程調用,得到鎖對象;使用synchronized關鍵字,當線程A嘗試執行同步代碼塊,而線程B正在執行,那麼A將會掛起,直到B執行完; 而是用Lock接口,調用tryLock將返回Boolean類型,能夠控制當前線程是要掛起仍是繼續執行下面的代碼;
  • Lock接口容許讀和寫操做分離;多個讀線程或一個寫線程;
  • Lock接口有比synchronized更好的性能;

 下面展現一個簡單的例子ide

動手實現

1.建立PrintQueue源碼分析

public class PrintQueue {
    private final Lock queueLock=new ReentrantLock();

    public void printJob(Object document) {
        queueLock.lock();
        try {
            Long duration=(long)(Math.random()*10000);
            System.out.printf("%s:PrintQueue: Printing a Job during %d seconds\n",Thread.currentThread().getName(),(duration/1000));
            Thread.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            queueLock.unlock();
        }
    }
}

2.建立一個Job

public class Job implements Runnable {
    private PrintQueue printQueue;

    public Job(PrintQueue printQueue) {
        this.printQueue = printQueue;
    }

    @Override
    public void run() {
        System.out.printf("%s: Going to print a document\n", Thread.currentThread().getName());
        printQueue.printJob(new Object());
        System.out.printf("%s: The document has been printed\n",Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        PrintQueue printQueue=new PrintQueue();
        Thread thread[]=new Thread[10];
        for (int i=0; i<10; i++){
            thread[i]=new Thread(new Job(printQueue),"Thread "+ i);
        }

        for (int i=0; i<10; i++){
            thread[i].start();
        }
    }
}

要點

在lock以後必定要解鎖性能

簡單源碼分析

Lock的接口中的全部方法:this

void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();


Lock接口的主要實現類是ReentrantLock,該類是Lock類的加強實現,好比該類中有
public final boolean hasQueuedThread(Thread thread);
public final int getQueueLength();
protected Collection<Thread> getQueuedThreads();
public boolean hasWaiters(Condition condition);
public int getWaitQueueLength(Condition condition);
這些方法能夠獲取線程運行時的更多信息;

這裏注意 tryLock()和lock()方法的區別,tryLock方法直接返回,而lock方法可能會使線程掛起;更加要注意的是使用Lock必定要注意不要形成DeadLock;

spa

相關文章
相關標籤/搜索