javasemaphore实现等待队列问题为啥死锁

author author     2023-05-13     523

关键词:

两个生产者,每个都生产三十次。
两个消费者,每个都消费三十次。
篮子初始化四个苹果,总容量十个。
full 为 semaphone(4)
empty 为 semaphore(6)
mutex 为全局锁 semaphore(1)
消费者:
full.Wait();
mutex.Wait();
消费....
mutex.Signal();
empty.Signal();

生产者:
empty.Wait();
mutex.Wait();
生产....
mutex.Signal();
full.Signal

Semaphore 同步的 Wait()
this.value--;
if(value<0) wait; // 省略 try catch
.

常规的 Semaphore 使用 while(value < 0) 控制 wait(). 但是上述的 Semaphore 使用 while() 就死锁,使用 if 没有任何问题。
我的问题:
问题1:
两个消费者都 wait() 等待生产者时,生产者生产完 mutex.Signal() 中有 notify(), full.Signal() 中又有 notify(), 这里唤醒了大家几次?
问题2:
两个消费者都 wait() 等待生产者时,生产者生产完一个通知大家,如果等待的消费者1抢到机会开始消费,之后释放mutex锁时 notify() 通知大家,如果等待的消费者2抢到机会消费,但是却是没有可以消费的... 这里是怎么造成的那?

谢谢
因为标准的 Semaphore 不允许负值,使用 while(value<=0) 进行 wait(), 然后才能 value--.

但是如果允许负值,则可以实现等待队列。这个问题就是要实现队列。如果使用 value--; while(value<0) wait() 就会死锁,但是需要修改为 if 才没有死锁。这是为什么那?

比如有两个线程执行,线程t1, 线程t2 t1 需要获取方法A的锁标志,同时方法A调用了方法B,t1获取了A的锁标志,并获取了B的锁标志,才能完成执行 同时t2也在执行,t2获取方法B的锁标志,方法B调用了方法A,t2也需要获取两个方法A,B的锁标志才能执行完成 当t1 获取了A方法的锁标志,同时t2获取了B方法的锁标志 那么t1会等待t2释放方法B的锁标志,t2也在等待t1释放方法A的锁标志,这样就形成了死锁,都在等待.... 参考技术A class Stack<T> private Vector<T> v; public Stack() v = new Vector<T>(); public T pop() if (v.size()==0) return null; return v.get(v.size()-1); public void push(T t) v.add(t); public boolean isEmpty() return v.size()==0; class Queue<T> private Vector<T> v; public Queue() v = new Vector<T>(); //入队列 public void enqueue(T t) v.add(t); //出队列 public T dequeue() if (v.size()==0) return null; return v.get(0); public boolean isEmpty() return v.size() == 0;

为啥在使用等待组和通道时会出现死锁?

】为啥在使用等待组和通道时会出现死锁?【英文标题】:whyistheredeadlockwhenusingwaitgroupandchannelingo?为什么在使用等待组和通道时会出现死锁?【发布时间】:2022-01-1010:46:47【问题描述】:我想使用setter函数将0-9发送到ch1通道,然... 查看详情

深入理解gcd

前言 首先提出一些问题: dispatch_async函数如何实现,分发到主队列和全局队列有什么区别,一定会新建线程执行任务么?dispatch_sync函数如何实现,为什么说GCD死锁是队列导致的而不是线程,死锁不是操作系统的概念么?... 查看详情

深入了解gcd

首先提出一些问题:dispatch_async 函数如何实现,分发到主队列和全局队列有什么区别,一定会新建线程执行任务么? dispatch_sync 函数如何实现,为什么说GCD死锁是队列导致的而不是线程,死锁不是操作系统的概念么?&n... 查看详情

理队列等待之tx-allocate

【故障处理】队列等待之TX-allocateITLentry引起的死锁处理  一.1 前言部分一.1.1 导读和注意事项各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~:①enq:TX-all... 查看详情

深入理解gcd

...入理解GCD前言首先提出一些问题:dispatch_async 函数如何实现,分发到主队列和全局队列有什么区别,一定会新建线程执行任务么?dispatch_sync 函数如何实现,为什么说GCD死锁是队列导致的而不是线程,死锁不是操作系统的... 查看详情

Core Data 私有队列死锁

...数据。在我的应用程序委托的applicationShouldTerminate中,我等待后台线程完成其工作时释放的信号量。这是为了避免在工作过程中杀死线程并使事情处于不一致的状态。不幸的是,这会导致死锁。以下是后台作业的运行方式:_co 查看详情

关于oracle数据库死锁,请大神进。为啥用javasynchronized关键字解决不了?怎么解决死锁问题?

...发生死锁(a,b同时分别被不同用户提交的事务锁住,互相等待),要在linux关掉oracle进程重启才可以。这个问题用程序怎么来解决?我建议老大说,在java程序事务所在的方法加一个synchronized关键字,锁住该方法,老大说这种做法不... 查看详情

死锁相关问题

...称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。系统发生死锁现象不仅浪费大量的系统资源,甚至导致整个系统崩溃,带来灾难性后果。 二、死锁产生的原因是什么?死锁产生的四个必要... 查看详情

C++中阻塞队列和屏障的死锁

...什么。消息可以是:-1(流结束->终止),-2(屏障->等待所有线程到达它,然后继续),其他值进行随机计算。循环按以下顺序完成:一些计 查看详情

java的monitor机制中,为啥阻塞队列用list等待队列用set

...队列中添加一个元素,至于元素存放的位置与具体队列的实现有关。移除操作将会移除队列的头部元素,并将这个移除的元素作为返回值反馈给调用者。检查操作是指返回队列的头元素给调用者,队列不对这个头元素进行删除处... 查看详情

为啥我们要“使用 2 个堆栈实现一个队列”? [复制]

】为啥我们要“使用2个堆栈实现一个队列”?[复制]【英文标题】:Whydowedo"implementaqueueusing2stacks"?[duplicate]为什么我们要“使用2个堆栈实现一个队列”?[复制]【发布时间】:2011-11-1518:15:48【问题描述】:可能重复:Whyuse... 查看详情

死锁面试题

...以引入超时机制,避免等待时间过长而出现死锁的情况。实现资源预分配机制。在系统启动时,对资源进行预分配,避免资源争夺的情况。实现死锁检测和解除机制。通过监控系统中进程的资源占用情况,及时发现死锁的情况并... 查看详情

使用通道作为队列的死锁

...2021-08-2023:37:15【问题描述】:我正在学习Go,我正在尝试实现一个作业队列。我想做的是:让主要的goroutine通过一个通道为多个解析器提供行(将一行解析为s结构),并让每个解析器将结构发送到其他工作器(goroutine)将处理的... 查看详情

主队列中添加的同步操作(dispatch_sync)永远不会被执行,会死锁原因

...e,block),所添加的任务:block;一.主队列特点:后面的任务必须等待前面的任务执行完成才可以进行执行,不能插队;二.同步添加任务:dispatch_sync(main_queue,block)函数的特点:必须等待其所提交的任务block执行完成,此函数才能返回,函数返回... 查看详情

后台工作人员中异步等待中的调解员死锁-如何检测线程调用自身

】后台工作人员中异步等待中的调解员死锁-如何检测线程调用自身【英文标题】:Mediatordeadlockonasyncawaitwithinbackgroundworker-howtodetectthreadcallingitself【发布时间】:2020-08-2816:34:42【问题描述】:我有一个中介,我最近需要在后台线... 查看详情

countdownlatch导致的多线程死锁

参考技术Acountdownlatch是通过计数器实现的,初始化时定义count数,每一个线程执行完将count数-1.当count=0时表示所以线程执行完毕,可以进入接下来的逻辑。countdownlatch的await()方法是等待count=0,执行此方法时,执行完的线程会进入... 查看详情

锁标记如果过多,就会出现线程等待其他线程释放锁标记(代码片段)

锁标记如果过多,就会出现线程等待其他线程释放锁标记,而又都不释放自己的锁标记供其他线程运行的状况。就是死锁。死锁的问题通过线程间的通信的方式进行解决。线程间通信机制实际上也就是协调机制。线程间通信使用... 查看详情

多线程处理怎么使用绿联

...行队列、主队列特性:先进先出。答案:由于队列的循环等待,会产生死锁的现象原因:首先,我们在主队列中,提交了一个viewDidLoad任务,然后,我们又提交了一个block任务,无论哪一个任务,都将会由主线程中执行,首先,vi... 查看详情