學習Java併發已經有一個多月了,感受有些東西學習一下子了就會忘記,作了一些筆記可是不繫統,對於Java併發這麼大的「系統」,須要本身好好總結、整理才能征服它。但願同仁們一塊兒來學習Java併發編程,共同進步,互相指導。編程
在學習Java併發以前咱們須要先理解一些基本的概念:共享、可變、線程安全性、線程同步、原子性、可見性、有序性。安全
要編寫線程安全的代碼,其核心在於對共享的和可變的狀態進行訪問。多線程
「共享」就意味着變量能夠被多個線程同時訪問。咱們知道系統中的資源是有限的,不一樣的線程對資源都是具備着同等的使用權。有限、公平就意味着競爭,競爭就有可能會引起線程問題。併發
「可變」是指變量的值在其生命週期內是能夠發生改變的。「可變」對應的是「不可變」。咱們知道不可變的對象必定是線程安全的,而且永遠也不須要額外的同步(由於一個不可變的對象只要構建正確,其外部可見狀態永遠都不會發生改變)。因此「可變」意味着存在線程不安全的風險。解決辦法:異步
一、不在線程中共享該狀態變量,能夠將變量封裝到方法中。學習
二、將狀態變量修改成不可變的變量(final)。線程
三、訪問狀態變量時使用同步策略。對象
四、使用原子變量類。排序
線程安全是一個比較複雜的概念。其核心概念就是正確性。所謂正確性就是某各種的行爲與其規範徹底一致,即其近似與「所見即所知(we know it when we see it)」。當多個線程訪問某各種時,無論運行時環境採用何種調度方式或者這些線程將如何交替執行,而且在主調代碼中不須要任何額外的同步或者協同,這個類都能表現出正確的行爲,那麼就稱這個類是線程安全的。(引自:《Java併發編程實戰》)生命週期
線程經過其核心就在於一個「同」。所謂「同」就是協同、協助、配合,「同步」就是協同步調昨,也就是按照預約的前後順序進行運行,即「你先,我等, 你作完,我再作」。
線程同步,就是當線程發出一個功能調用時,在沒有獲得結果以前,該調用就不會返回,其餘線程也不能調用該方法。就通常而言,咱們在說同步、異步的時候,特指那些須要其餘組件來配合或者須要必定時間來完成的任務。在多線程編程裏面,一些較爲敏感的數據時不容許被多個線程同時訪問的,使用線程同步技術,確保數據在任什麼時候刻最多隻有一個線程訪問,保證數據的完整性。
線程同步的機制主要有:臨界區、互斥量、事件、信號量四種方式
一、臨界區:經過對多線程的串行化來訪問公共資源或一段代碼,速度快,適合控制數據訪問。在任意時刻只容許一個線程對共享資源進行訪問,若是有多個線程試圖訪問公共資源,那麼在有一個線程進入後,其餘試圖訪問公共資源的線程將被掛起,並一直等到進入臨界區的線程離開,臨界區在被釋放後,其餘線程才能夠搶佔。
二、互斥量:採用互斥對象機制。 只有擁有互斥對象的線程纔有訪問公共資源的權限,由於互斥對象只有一個,因此能保證公共資源不會同時被多個線程訪問。互斥不只能實現同一應用程序的公共資源安全共享,還能實現不一樣應用程序的公共資源安全共享。
三、信號量:它容許多個線程在同一時刻訪問同一資源,可是須要限制在同一時刻訪問此資源的最大線程數目。
四、事 件: 經過通知操做的方式來保持線程的同步,還能夠方便實現對多個線程的優先級比較的操做。
【引自:百度百科】
原子是世界上最小的單位,具備不可分割性。在咱們編程的世界裏,某個操做若是不可分割咱們就稱之爲該操做具備原子性。例如:i = 0,這個操做是不可分割的,因此該操做具備原子性。若是某個操做能夠分割,那麼該操做就不具有原子性,例如i++。非原子操做都存在線程安全問題,這個時候咱們須要使用同步機制來保證這些操做變成原子操做,來確保線程安全。
線程可見性是指線程之間的可見性,即一個線程對狀態的修改對另外一個線程是可見的,也就是一個線程修改的結果,另一個線程立馬就知道了。好比volitile修飾的變量,就具有可見性。
有序性指的是數據不相關的變量在併發的狀況下,實際執行的結果和單線程的執行結果是同樣的,不會由於重排序的問題致使結果不可預知。volatile, final, synchronized,顯式鎖均可以保證有序性。