什麼是線程:一個程序執行多個任務,每一個人任務稱爲一個線程.多線程程序是能夠同時運行多個一個以上的線程的程序. java
具體理解:同一時間運行多個線程,多個線程對同一數據資源進行處理,可能會形成數據的失真性,具體例子參考:<java核心技術.卷一>P640頁銀行轉錢問題.由於對線程的管理不當,形成數據的錯誤.因此出現了一系列操做管理線程的技巧. 安全
一.線程同步 多線程
1.鎖對象 併發
有兩種機制防止代碼受併發訪問的干擾,java提供了synchronized關鍵字,和java5.0 app
引入的ReentrantLock類(做用:構建一個能夠用來被保護臨界區的可重入鎖). spa
ReentrantLock保護代碼塊的基本結構以下: 線程
private Lock mylock = new ReentrantLock(); mylock.lock(); try { }finally { mylock.unlock(); }
把解鎖操做放到finally句子裏,防止在臨界區的代碼拋出異常,鎖必須被釋放,不然,線程永遠被阻塞. 設計
或許又想,若是建立多個對象,多個對象獲得不一樣的鎖對象,多個線程都不會發生阻塞? code
鎖是可重入的,由於線程能夠重複的得到已經持有的鎖.鎖保持一個持有計數來跟蹤對lock方法的嵌套調用.而且lock()方法的做用是獲取這個鎖,若是同時被另外一個線程擁有則發生阻塞. orm
2.條件對象:
線程進入臨界區,卻發如今某一個條件知足後他才能執行.要使用一個條件對象來管理已經得到了一個鎖可是卻不能作有用工做的線程.
private Lock mylock = new ReentrantLock(); private Condition condition = myLock.newCondition(); // 得到條件對象
說白了就是ReentrantLock只能鎖住線程,條件對象能夠對線程進行一些操做,如await()將進程放到條件等待集中,signallAll()解除該條件等待集中的全部線程的阻塞狀態,signal()從條件等待集中隨機選擇一個線程,解除阻塞狀態.
3.synchronized關鍵字
同步阻塞:
private Object lock = new Object(); // 經過一個對象鎖來實現額外的原子操做 synchronized (lock) { // 多個線程不能共同訪問synchronized塊內容,同一時刻只有一個線程能訪問 lock.notifyAll(); // 喚醒其餘線程繼續競爭synchronized塊內容 }
4.volatile
volatile是一個類型修飾符。它是被設計用來修飾被不一樣線程訪問和修改的變量.volatile保證了線程能夠正確的讀取其餘線程的寫入的值,可見ref JMM happens-before原則,多個線程能夠共同訪問這個類型變量的內容.
5.讀寫鎖
java.util.concurrent.Locks定義了兩個鎖類:ReentrantReadWriteLock和ReentrantLock.
// 構造一個ReentrantReadWriteLock對象 private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); // 抽取讀鎖和寫鎖 private Lock readLock = rwl.readLock(); private Lock writeLock = rwl.writeLock(); // 對全部獲取方法加讀鎖: public double getXXX() { readLock.lock(); try { } finally { readLock.unLock(); } } // 對全部修改方法加寫鎖: public double setXXX() { writeLock.lock(); try { } finally { writeLock.unLock(); } }
Lock readLock() // 獲得一個能夠被多個讀操做共用的讀鎖,排斥全部寫操做.
Lock writeLock() // 獲得一個寫鎖,排斥全部其餘的讀操做和寫操做
二.阻塞隊列:
阻塞隊列與普通隊列的區別在於,當隊列是空的時,從隊列中獲取元素的操做將會被阻塞,或者當隊列是滿時,往隊列裏添加元素的操做會被阻塞。試圖從空的阻塞隊列中獲取元素的線程將會被阻塞,直到其餘的線程往空的隊列插入新的元素。一樣,試圖往已滿的阻塞隊列中添加新元素的線程一樣也會被阻塞,直到其餘的線程使隊列從新變得空閒起來.
三.線程的安全集合
四.執行器:
線程池
五.同步器: