在併發編程場景下如何保證車票或者商品出售業務是線程安全的?
首先我們就會想到加鎖,來保證出售業務線程安全。但是加鎖勢必會帶來性能上的瓶頸。那麼我們就會思考,還有沒有其它的方式避免加鎖來實現同樣的效果呢?
這裏我們帶着這個問題,先採用常見的加鎖方式來實現。
package com.sync.ticket;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.TimeUnit;
/**
* 12306有N張代售車票或者庫存有N件商品
*
* @author 小輝GE/小輝哥
* <p>
* 2019年8月11日 下午19:40:00
*/
public class TicketSellerSync {
static List<String> tickets = new ArrayList<>();
//static List<String> tickets = new Vector<>();
static {
for (int i = 0; i < 1000; i++) tickets.add("車票/商品編號:" + i);
}
public static void main(String[] args) {
/*for (int i = 0; i < 10; i++) {
new Thread(() -> {
while (tickets.size() > 0) {
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(tickets.remove(0) + "已賣出");
}
}).start();
}*/
for (int i = 0; i < 10; i++) {
new Thread(() -> {
while (true) {
synchronized (tickets) {
if (tickets.size() <= 0) break;
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(tickets.remove(0) + "已賣出");
}
}
}).start();
}
}
}
測試輸出結果如下(輸出結果比較多,我們只截取部分):
結果分析:
我們可以看出加鎖是肯定能保證線程安全,保證車票或者商品出售業務不會重複,或者超出範圍。那麼,我們只能加鎖來實現嗎,有沒有更高效的不用加鎖的方式,其實是有的,我們可以用線程安全的同步隊列來實現,但是一定要保證操作方法是原子性的。下一篇我們會用ConcurrentLinkedQueue的方式來實現。
以上代碼僅供參考,如有不當之處,歡迎指出!!!
更多幹貨,歡迎大家關注和聯繫我。期待和大家一起更好的交流、探討技術!!!