成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

喝了100杯醬香拿鐵,我開竅了

開發 后端
使用“越細粒度的鎖越好”,真的是這樣嗎?會不會產生一些其它問題?通過對醬香拿鐵進行排序,解決了死鎖問題,避免循環等待,效率也得到了提升。

大家好,我是哪吒。

上一篇提到了鎖粒度的問題,使用“越細粒度的鎖越好”,真的是這樣嗎?會不會產生一些其它問題?

先說結論,可能會產生死鎖問題。

下面還是以購買醬香拿鐵為例:

1、定義咖啡實體類Coffee

@Data
public class Coffee {
    // 醬香拿鐵
    private String name;

    // 庫存
    public Integer inventory;

    public ReentrantLock lock = new ReentrantLock();
}

2、初始化數據

private static List<Coffee> coffeeList = generateCoffee();

public static List<Coffee> generateCoffee(){
    List<Coffee> coffeeList = new ArrayList<>();
    coffeeList.add(new Coffee("醬香拿鐵1", 100));
    coffeeList.add(new Coffee("醬香拿鐵2", 100));
    coffeeList.add(new Coffee("醬香拿鐵3", 100));
    coffeeList.add(new Coffee("醬香拿鐵4", 100));
    coffeeList.add(new Coffee("醬香拿鐵5", 100));
    return coffeeList;
}

3、隨機獲取n杯咖啡

// 隨機獲取n杯咖啡
private static List<Coffee> getCoffees(int n) {
    if(n >= coffeeList.size()){
        return coffeeList;
    }

    List<Coffee> randomList = Stream.iterate(RandomUtils.nextInt(n), i -> RandomUtils.nextInt(coffeeList.size()))
            .distinct()// 去重
            .map(coffeeList::get)// 跟據上面取得的下標獲取咖啡
            .limit(n)// 截取前面 需要隨機獲取的咖啡
            .collect(Collectors.toList());
    return randomList;
}

4、購買咖啡

private static boolean buyCoffees(List<Coffee> coffees) {
    //存放所有獲得的鎖
    List<ReentrantLock> locks = new ArrayList<>();
    for (Coffee coffee : coffees) {
        try {
            // 獲得鎖3秒超時
            if (coffee.lock.tryLock(3, TimeUnit.SECONDS)) {
                // 拿到鎖之后,扣減咖啡庫存
                locks.add(coffee.lock);
                coffeeList = coffeeList.stream().map(x -> {
                 // 購買了哪個,就減哪個
                    if (coffee.getName().equals(x.getName())) {
                        x.inventory--;
                    }
                    return x;
                }).collect(Collectors.toList());
            } else {
                locks.forEach(ReentrantLock::unlock);
                return false;
            }
        } catch (InterruptedException e) {
        }
    }
    locks.forEach(ReentrantLock::unlock);
    return true;
}

3、通過parallel并行流,購買100次醬香拿鐵,一次買2杯,統計成功次數

public static void main(String[] args){
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();

    // 通過parallel并行流,購買100次醬香拿鐵,一次買2杯,統計成功次數
    long success = IntStream.rangeClosed(1, 100).parallel()
            .mapToObj(i -> {
                List<Coffee> getCoffees = getCoffees(2);
                //Collections.sort(getCoffees, Comparator.comparing(Coffee::getName));
                return buyCoffees(getCoffees);
            })
            .filter(result -> result)
            .count();

    stopWatch.stop();
    System.out.println("成功次數:"+success);
    System.out.println("方法耗時:"+stopWatch.getTotalTimeSeconds()+"秒");
    for (Coffee coffee : coffeeList) {
        System.out.println(coffee.getName()+"-剩余:"+coffee.getInventory()+"杯");
    }
}

耗時有點久啊,20多秒。

數據對不對?

  • 醬香拿鐵1賣了53杯。
  • 醬香拿鐵2賣了57杯。
  • 醬香拿鐵3賣了20杯。
  • 醬香拿鐵4賣了22杯。
  • 醬香拿鐵5賣了19杯。
  • 一共賣了171杯。

數量也對不上,應該賣掉200杯才對,哪里出問題了?

4、使用visualvm測一下:

果不其然,出問題了,產生了死鎖。

線程 m 在等待的一個鎖被線程 n 持有,線程 n 在等待的另一把鎖被線程 m 持有。

  1. 比如美杜莎買了醬香拿鐵1和醬香拿鐵2,小醫仙買了醬香拿鐵2和醬香拿鐵1;
  2. 美杜莎先獲得了醬香拿鐵1的鎖,小醫仙獲得了醬香拿鐵2的鎖;
  3. 然后美杜莎和小醫仙接下來要分別獲取 醬香拿鐵2 和 醬香拿鐵1 的鎖;
  4. 這個時候鎖已經被對方獲取了,只能相互等待一直到 3 秒超時。

5、如何解決呢?

讓大家都先拿一樣的醬香拿鐵不就好了。讓所有線程都先獲取醬香拿鐵1的鎖,然后再獲取醬香拿鐵2的鎖,這樣就不會出問題了。

也就是在隨機獲取n杯咖啡后,對其進行排序即可。

// 通過parallel并行流,購買100次醬香拿鐵,一次買2杯,統計成功次數
long success = IntStream.rangeClosed(1, 100).parallel()
        .mapToObj(i -> {
            List<Coffee> getCoffees = getCoffees(2);
            // 根據咖啡名稱進行排序
            Collections.sort(getCoffees, Comparator.comparing(Coffee::getName));
            return buyCoffees(getCoffees);
        })
        .filter(result -> result)
        .count();

6、再測試一下

  • 成功次數100。
  • 咖啡賣掉了200杯,數量也對得上。
  • 代碼執行速度也得到了質的飛躍,因為不用沒有循環等待鎖的時間了。

看來真的不是越細粒度的鎖越好,真的會產生死鎖問題。通過對醬香拿鐵進行排序,解決了死鎖問題,避免循環等待,效率也得到了提升。

責任編輯:姜華 來源: 哪吒編程
相關推薦

2021-12-03 10:46:49

ELKGraylog運維

2021-12-02 06:34:34

GraylogELK日志

2023-11-09 14:12:23

獎項

2020-12-21 07:36:15

緩存數據庫緩存層

2022-12-30 17:18:04

2021-12-05 23:17:18

iOS蘋果系統

2016-07-04 18:18:32

歐洲杯

2025-06-25 09:31:41

2020-01-21 21:15:16

WiFi網絡WiFi6

2020-07-03 15:10:35

Java Rust 開發

2023-12-13 08:11:36

2021-01-11 08:03:30

阿里中臺項目

2010-11-24 10:41:32

2021-12-15 06:18:23

iOS15.2蘋果 iOS

2024-01-26 07:48:10

SpringKafka提升

2024-01-05 13:26:00

KafkaTopicSpring

2025-07-04 09:31:56

2019-08-05 15:01:10

遠程醫療醫療保健就診

2021-04-28 08:51:53

計算機網絡安全
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91精品一区二区三区久久久久久 | 国产精品999 | 中文字幕日韩欧美一区二区三区 | 中文字幕99 | 天天躁人人躁人人躁狂躁 | 欧美一级艳情片免费观看 | 亚洲一区二区视频 | 久久久精 | 在线国产视频 | 亚洲精品av在线 | 97人人草 | 国产精品美女久久久久 | 99精品欧美一区二区三区综合在线 | 久久久久久亚洲欧洲 | 久久综合一区 | 国产黄色在线观看 | 国产伦一区二区三区视频 | 成人国产精品视频 | 91精品国产一二三 | 日本在线视频不卡 | 久久久久久久一区 | 日韩一二三 | 国产在线1区 | avmans最新导航地址 | 日韩精品在线观看网站 | 久久人人爽人人爽 | 日韩午夜网站 | 欧美激情在线精品一区二区三区 | 狠狠视频 | 亚洲狠狠爱一区二区三区 | 蜜桃一区 | 国产亚洲精品久久久优势 | 亚洲国产精品一区 | 国产男人的天堂 | 久久久久久久久中文字幕 | 99精品视频网 | 久久国 | 黄网站在线观看 | 欧美另类视频 | 日韩国产中文字幕 | 爱综合 |