Java并發(1)-基礎概念
這是將是一系列關于Java并發基礎知識的文章。事實上,主要是《實戰Java高并發程序設計》的讀書筆記和網絡資料以及對它們的整理。
相關概念
1.同步Synchronous和異步Asynchronous
同步和異步通常是用來形容一次方法調用。
所謂同步,就是在發出一個”調用”時,在沒有得到結果之前,該”調用”就不返回。但是一旦調用返回,就得到返回值了。換句話說,就是由”調用者”主動等待這個”調用”的結果。
而異步則是相反,”調用”在發出之后,這個調用就直接返回了,所以沒有返回結果。換句話說,當一個異步過程調用發出后,調用者不會立刻得到結果。而是在”調用”發出后,”被調用者”通過狀態、通知來通知調用者,或通過回調函數處理這個調用。
來自>知乎 怎樣理解阻塞非阻塞與同步異步的區別?
2.并發、并行
并發和并行的區別就是一個處理器同時處理多個任務和多個處理器或者是多核的處理器同時處理多個不同的任務。前者是邏輯上的同時發生,而后者是物理上的同時發生。
并發性(concurrency),又稱共行性,是指能處理多個同時性活動的能力,并發事件之間不一定要同一時刻發生。
并行(parallelism)是指同時發生的兩個并發事件,具有并發的含義,而并發則不一定并行。
來個比喻:并發和并行的區別就是一個人同時吃三個饅頭和三個人同時吃三個饅頭。
來自> 并發和并行的區別:吃饅頭的比喻
3. 臨界區
用來表示一種公共資源可以被多個線程使用,但是每次只允許一個線程使用它,一旦臨界區資源被占用,其他資源想要訪問它只能等待。
4. 堵塞和非堵塞
堵塞和非堵塞用來形容線程相互影響的一種狀態,比如一個線程占用了臨界區資源,那么其他所以線程需要使用這個資源并且等待,等待會導致線程掛起,這便是堵塞。非堵塞相反,表示線程沒有被其他線程妨礙,會不斷嘗試向前執行。
5. 死鎖(Deadlock)、饑餓(Starvation)和活鎖(Livelock)
死鎖饑餓和活鎖都是用來形容多線程的活躍性。
- 死鎖:是指兩個或者兩個以上的進程執行過程中,由于競爭資源或者由于彼此通信而造成的一種堵塞的現象,若無外力的作用,他們都將無法推進下去。
- 饑餓:是指線程一直無法獲取資源,導致一個堵塞。例如可能是因為優先級太低,而高優先級的線程一直搶占它需要的資源導致低級線程無法工作。
- 活鎖:是指任務或者執行者沒有被阻塞,由于某些條件沒有滿足,導致一直重復嘗試,失敗,嘗試,失敗。
并發級別
由于臨界區的存在,多線程之間的并發必須受到控制。根據控制并發的策略,我們可以把并發的級別進行分類,大致上可以分為阻塞、無饑餓、無障礙、無鎖、無等待幾種。
1.堵塞(Blocking)
一個線程是阻塞的,那么在其他線程釋放資源之前,當前線程無法繼續執行。
2.無饑餓(Starvation-Free)
如果鎖是公平的,滿足所有的線程按照順序排隊(高優先級的線程不插隊),那么所有的線程都有執行機會。
3.無障礙(Obstruction-Free)
表示所有線程都可以訪問臨界區,為了保證數據安全,如果線程發生沖突就回滾。
4.無鎖(Lock-Free)
在無鎖的情況下,所有的線程都能嘗試對臨界區進行訪問,但不同的是,無鎖的并發保證必然有一個線程能夠在有限步內完成操作離開臨界區。
5.無等待(Wait-Free)
無鎖只要求有一個線程可以在有限步內完成操作,而無等待則在無鎖的基礎上更進一步進行擴展。它要求所有的線程都必須在有限步內完成,這樣就不會引起饑餓問題。如果限制這個步驟上限,還可以進一步分解為有界無等待和線程數無關的無等待幾種,它們之間的區別只是對循環次數的限制不同。
一種典型的無等待結構就是 RCU(Read-Copy-Update)。它的基本思想是,對數據的讀可以不加控制。
原子性、可見性、有序性
Java內存模型是圍繞著并發過程中如何處理原子性、可見性、有序性這三個特征來建立的,下面是這三個特性的實現原理:
1.原子性(Atomicity)
原子性表示一個操作不可中斷,即使在多個線程一起執行的時候,一個操作一旦開始就不會被其他線程干擾。
2.可見性(Visibility)
可見性是指當一個線程修改了某一個共享變量的值,其他線程是否能夠立即知道這個修改。
3.有序性(Ordering)
有序性問題的原因是因為程序在執行時,可能會進行指令重排,重排后的指令與原指令的順序未必一致。
來自: http://www.qinglinyi.com/posts/java-concurrency-0/