目的
保护一组资源中的每个资源都不会受到并发访问而导致不一致
例子代码
男: 砸了你的摊, 逼着你离开, 最后知道真相的我眼泪掉下来, 砸了你的摊, 我背了良心债, 就算付出再多感情也再买不回来
女: 当初是你要分开, 分开就分开, 如今又要用真(政)爱(策), 把我哄回来, 摆摊不是你想摆, 想摆就能摆, 让我挣开, 让我明白, 放手你的爱
摆摊经济一出, 各国人都开启了摆摊之旅:
可是摊位有限, 不能随便摆哦, 我们来讲讲这里面的故事:
我们定义一下货物类:
//商品@Data@AllArgsConstructorpublic class Goods { private String name;}
定义一个摊位类:
//摊位@Data@AllArgsConstructorpublic class Stall { private Integer number; private String name; private List<Goods> saleGoods;}
定义一个摆摊的人:
//摆摊人@Data@AllArgsConstructorpublic class People { private String name; private List<Goods> saleGoods;}
我们三个人同时去摆摊:
List<People> peopleList = new ArrayList<>();peopleList.add(new People("小李", Arrays.asList(new Goods("小李皮鞋"), new Goods("小李运动鞋"))));peopleList.add(new People("小王", Arrays.asList(new Goods("小王西瓜"), new Goods("小王椰子"))));peopleList.add(new People("小张", Arrays.asList(new Goods("小张肥皂"), new Goods("小张洗衣液"))));List<Stall> stallList = new ArrayList<>();stallList.add(new Stall(1,"摊位一",new ArrayList<>()));stallList.add(new Stall(2,"摊位二",new ArrayList<>()));peopleList.parallelStream().forEach( (people) -> { for (Stall stall : stallList) { if(stall.getSaleGoods().isEmpty()) { stall.setName(people.getName() + "的摊位"); //拜访货物中 putGoods2Stall(); stall.setSaleGoods(people.getSaleGoods()); }} });System.out.println(stallList.toString());
输出:
[Stall(number=1, name=小李的摊位, saleGoods=[Goods(name=小李皮鞋), Goods(name=小李运动鞋)]), Stall(number=2, name=小王的摊位, saleGoods=[Goods(name=小张肥皂), Goods(name=小张洗衣液)])]
问题分析
这个和互斥模式是一样的, 主要是状态的不一致, 小王卖了小张的货, 如果用互斥模式来解决也没什么问题, 就是如果对stallList 加锁粒度太大, 并发不高, 如果是对单个摊位加锁, 要注意加锁顺序, 代码也会复杂一些.
信号量模式
List<People> peopleList = new ArrayList<>();peopleList.add(new People("小李", Arrays.asList(new Goods("小李皮鞋"), new Goods("小李运动鞋"))));peopleList.add(new People("小王", Arrays.asList(new Goods("小王西瓜"), new Goods("小王椰子"))));peopleList.add(new People("小张", Arrays.asList(new Goods("小张肥皂"), new Goods("小张洗衣液"))));Semaphore semaphore = new Semaphore(2);peopleList.parallelStream().forEach( (people) -> { try { semaphore.acquire(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println(people.getName() + "开始摆摊"); Stall stall = new Stall(); stall.setName(people.getName() + "的摊位"); //摆放货物中 putGoods2Stall(); stall.setSaleGoods(people.getSaleGoods()); System.out.println(LocalDateTime.now() + "" + stall.toString()); semaphore.release(); });
输出:
小王开始摆摊小李开始摆摊2020-06-06T13:04:03.710Stall(number=null, name=小王的摊位, saleGoods=[Goods(name=小王西瓜), Goods(name=小王椰子)])2020-06-06T13:04:03.710Stall(number=null, name=小李的摊位, saleGoods=[Goods(name=小李皮鞋), Goods(name=小李运动鞋)])小张开始摆摊2020-06-06T13:04:05.713Stall(number=null, name=小张的摊位, saleGoods=[Goods(name=小张肥皂), Goods(name=小张洗衣液)])
广告时间:
微信: