Java structured lock vs unstructured lock

來源:互聯網
上載者:User

標籤:sts   calling   記憶體   remove   cal   head   代碼   err   方法   

什麼是structured lock?先來段代碼:

public synchronized boolean contains(final Integer object) {        Entry pred = this.head;        Entry curr = pred.next;        while (curr.object.compareTo(object) < 0) {            pred = curr;            curr = curr.next;        }        return object.equals(curr.object);    }

這段代碼用synchronized來解決並發問題,這個例子是在方法上上鎖,也就是object層級,那麼一旦這個object被上鎖,該object的所有同步方法都會被鎖,鎖被釋放的時機是方法執行完畢,提到synchronized,也順便提一下wait/notify好了,看以下代碼:

public class Main {    public static void main(String[] args){        ThreadB b = new ThreadB();        b.start();        synchronized(b){            try{                System.out.println("Waiting for b to complete...");                b.wait();            }catch(InterruptedException e){                e.printStackTrace();            }            System.out.println("Total is: " + b.total);        }    }}class ThreadB extends Thread{    int total;    @Override    public void run(){        synchronized(this){            try {                sleep(2000);            } catch (InterruptedException e) {                System.out.println("wokao");            }            for(int i=0; i<100 ; i++){                total += i;            }            notify();        }    }}

  (這個程式一般運行不會有問題,但有個潛在的bug,誰能看出來)結合這個例子,兩句話基本能解釋

  1. wait() tells the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify( ).
  2. notify() wakes up the first thread that called wait() on the same object.

這種synchronized對同步機制,又稱為structured lock,因為看起來很結構化,很規整有沒有?

但是結果化對應對結果就是不夠靈活。什麼時候需要靈活呢?舉個例子

有這麼個鏈表A->B->C->D->E->F

假設有如下一組工作:

1.寫A和B;

2.寫B和C

3.寫C和D

4.寫D和E

5.寫E和F

如果用synchronized把1中的A和B鎖了,那麼2就必須等A和B都執行完成才能,執行,但是有必要嗎?其實只要等A結束,2就應該可以執行了,依次往下,這就是所謂的hand in hand locking,

就是連環鎖,描述如下:

lock A and B, start job 1

unlock A, lock C, start job 2

unlock B, lock D, start job 3 ...

這種連環鎖,顯然synchronized是做不到的,sychronized裡面可以套其他的synchronized,那隻能形成一個nested結構。

這就是synchronized或者說structured lock的局限性。

那麼這種情況下 unstructured lock就有用了,看一個使用的例子:

public static final class CoarseList extends ListSet {        /*         * TODO Declare a lock for this class to be used in implementing the         * concurrent add, remove, and contains methods below.         */        ReentrantLock lk= new ReentrantLock();        /**         * Default constructor.         */        public CoarseList() {            super();        }        /**         * {@inheritDoc}         *         * TODO Use a lock to protect against concurrent access.         */        @Override        boolean add(final Integer object) {            try{                lk.lock();                Entry pred = this.head;                Entry curr = pred.next;                while (curr.object.compareTo(object) < 0) {                    pred = curr;                    curr = curr.next;                }                if (object.equals(curr.object)) {                    return false;                } else {                    final Entry entry = new Entry(object);                    entry.next = curr;                    pred.next = entry;                    return true;                }            }finally {                lk.unlock();            }        }

  

這裡的ReentrantLock就很靈活,不過必須顯式地unlock,否則會出問題(就像c++必須顯示delete記憶體一樣),為了防止意外例如拋出exception,應該把unlock語句放在finally裡,所以這裡的弊端想必也能看到了吧,到處都要寫try finally語句!!!

unstructured lock還有個好處可以區分讀寫鎖,理論上多個線程讀不會有問題,所以用一個比較弱的讀寫鎖即可,而一旦有一個線程寫,其他線程就要注意了,最多隻能有一個線程在被鎖對象上寫,此時其他的線程無論讀還是寫,都得等。上例子:

public static final class RWCoarseList extends ListSet {        /*         * TODO Declare a read-write lock for this class to be used in         * implementing the concurrent add, remove, and contains methods below.         */        /**         * Default constructor.         */        public RWCoarseList() {            super();        }        /**         * {@inheritDoc}         *         * TODO Use a read-write lock to protect against concurrent access.         */        ReentrantReadWriteLock rwlk = new ReentrantReadWriteLock();        @Override        boolean add(final Integer object) {            try {                rwlk.writeLock().lock();                Entry pred = this.head;                Entry curr = pred.next;                while (curr.object.compareTo(object) < 0) {                    pred = curr;                    curr = curr.next;                }                if (object.equals(curr.object)) {                    return false;                } else {                    final Entry entry = new Entry(object);                    entry.next = curr;                    pred.next = entry;                    return true;                }            }finally {                rwlk.writeLock().unlock();            }        }

  

 

還沒完,unstructured lock的第三個好處是,支援trylock,看名字就可以看出來,就是先嘗試拿鎖,拿不到,做其他事去。想想synchronized是怎麼做的,先嘗試拿鎖,拿不到,block!高下立判

 

Java structured lock vs unstructured lock

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.