Java多線程同步

synchronized關鍵字
  • synchronized關鍵字修飾函數(shù)方法
    使用synchronized關鍵字時,會獲取java對象的內置鎖,內置鎖會保護整個方法。
public synchronized void add(){
    count++;
}

synchronized也可以修飾靜態(tài)方法,內置鎖會鎖住整改類。

  • synchronized關鍵字修飾代碼塊
    synchronized可以修飾代碼塊,只鎖住需要保護的代碼區(qū)域
public class SynchronizedThread {
    public void add(){
        synchronized(this)
        {
            count++;
        }
     }
}

synchronized是一種高開銷操作,實際應用不需要鎖住整個方法,可以使用同步代碼塊操作。

使用特殊域變量

使用volatile關鍵字修飾變量,沒有鎖同步開銷,每次使用變量時需要重新計算,不會直接使用寄存器的值,此變量不是原子操作,不可以修飾final對象。

public class SynchronizedThread{
    private volatile int count= 0;
    public void add(){
        count++;
    }
}
使用原子變量實現(xiàn)線程同步

在java的util.concurrent.atomic包中提供了創(chuàng)建了原子類型變量的工具類,使用該類可以簡化線程同步。

public class SynchronizedThread{
    private AtomicInteger count= new AtomicInteger(0);
    public void add(){
        count.addAndGet(1);
    }
}

原子操作適合線程簡單對象的計算。

使用重入鎖實現(xiàn)線程同步

在JavaSE5.0中新增了一個java.util.concurrent包來支持同步。ReentrantLock類是可重入、互斥、實現(xiàn)了Lock接口的鎖,它與使用synchronized方法和快具有相同的基本行為和語義,并且擴展了其能力。

public class SynchronizedThread{
    private int count= 0;
    private Lock lock = new ReentrantLock();
    public void add(){
        lock.lock();
        try{
             count++;
        }finally{
             lock.unlock();
        }
    }
}

使用try模塊語句,在finally模塊中釋放鎖,防止死鎖。
ReentrantLock類可以構造公平鎖,每個線程阻塞相同的時間,但由于能大幅度降低程序運行效率,不推薦使用。

使用局部變量實現(xiàn)線程同步

如果使用ThreadLocal管理變量,則每一個使用該變量的線程都獲得該變量的副本, 副本之間相互獨立,這樣每一個線程都可以隨意修改自己的變量副本,而不會對其他線程產生影響。

public class SynchronizedThread{
    private static ThreadLocal<Integer> count= new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue(){
            return 0;
        }
    };
    public void add(){
        count.set(count.get()+1);
    }
}
使用阻塞隊列實現(xiàn)線程同步

前面5種同步方式都是在底層實現(xiàn)的線程同步,但是我們在實際開發(fā)當中,應當盡量遠離底層結構。 使用javaSE5.0版本中新增的java.util.concurrent包將有助于簡化開發(fā)。 本小節(jié)主要是使用LinkedBlockingQueue<E>來實現(xiàn)線程的同步。

public class BlockingSynchronizedThread {
    private LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>();
    private class LinkBlockThread implements Runnable {
        @Override
        public void run() {
            try {
                int n = queue.take();
                System.out.println(n);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容