并发执行变成串行_网易Java研发面试官眼中的Java并发——安全性、活跃性、性能...
生活随笔
收集整理的這篇文章主要介紹了
并发执行变成串行_网易Java研发面试官眼中的Java并发——安全性、活跃性、性能...
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一. 安全性問題
Ⅰ. 數據競爭
數據競爭(Data Race):多個線程同時訪問同一數據,并且至少有一個線程會寫這個數據
1. add
private static final int MAX_COUNT = 1_000_000;private long count = 0;// 非線程安全public void add() { int index = 0; while (++index < MAX_COUNT) { count += 1; }}2. add + synchronized
private static final int MAX_COUNT = 1_000_000;private long count = 0;public synchronized long getCount() { return count;}public synchronized void setCount(long count) { this.count = count;}// 非線程安全public void add() { int index = 0; while (++index < MAX_COUNT) { setCount(getCount() + 1); }}- 假設count=0,當兩個線程同時執行getCount(),都會返回0
- 兩個線程執行getCount()+1,結果都是1,最終寫入內存是1,不符合預期,這種情況為竟態條件
Ⅱ. 竟態條件
- 如果程序存在竟態條件問題,那么意味著程序的執行結果是不確定的
1. 轉賬
public class Account { private int balance; // 非線程安全,存在竟態條件,可能會超額轉出 public void transfer(Account target, int amt) { if (balance > amt) { balance -= amt; target.balance += amt; } }}Ⅲ. 解決方案
面對數據競爭和竟態條件問題,可以通過互斥的方案來實現線程安全,互斥的方案可以統一歸為鎖
二. 活躍性問題
活躍性問題:某個操作無法執行下去,包括三種情況:死鎖、活鎖、饑餓
Ⅰ. 死鎖
- 互斥:不可破壞,鎖定目的就是為了互斥
- 占有且等待:一次性申請所有需要的資源
- 不可搶占:當線程持有資源A,并嘗試持有資源B時失敗,線程主動釋放資源A
- 循環等待:將資源編號排序,線程申請資源時按遞增(或遞減)的順序申請
Ⅱ. 活鎖
- 活鎖:線程并沒有發生阻塞,但由于相互謙讓,而導致執行不下去
- 解決方案:在謙讓時,嘗試等待一個隨機時間(分布式一致算法Raft也有采用)
Ⅲ. 饑餓
- 線程的優先級是不相同的,在CPU繁忙的情況下,優先級低的線程得到執行的機會很少,可能發生線程饑餓
- 持有鎖的線程,如果執行的時間過長(持有的資源不釋放),也有可能導致饑餓問題
- 保證資源充足
- 公平地分配資源(公平鎖) – 比較可行
- 避免持有鎖的線程長時間執行
三. 性能問題
- 假如p=95%,n無窮大,加速比S的極限為20,即無論采用什么技術,最高只能提高20倍的性能
Ⅰ. 解決方案
- 線程本地存儲(Thread Local Storage,TLS)
- 寫入時復制(Copy-on-write)
- 樂觀鎖
- JUC中的原子類
- Disruptor(無鎖的內存隊列)
- 使用細粒度鎖,例如JUC中的ConcurrentHashMap(分段鎖)
- 使用讀寫鎖,即讀是無鎖的,只有寫才會互斥的
Ⅱ. 性能指標
寫在最后
- 第一:看完點贊,感謝您的認可;
- ...
- 第二:隨手轉發,分享知識,讓更多人學習到;
- ...
- 第三:記得點關注,每天更新的!!!
- ...
總結
以上是生活随笔為你收集整理的并发执行变成串行_网易Java研发面试官眼中的Java并发——安全性、活跃性、性能...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python启动方法_python启动服
- 下一篇: java美元兑换,(Java实现) 美元