Java并发:排队队列问题

weixin_38049686 2019-09-12 03:42:19

我正在尝试从'信号量小书'中为'排队'问题编写一个解决方案。 问题描述如下: 想象一下,线程代表舞厅舞者,两种舞者,领导者和追随者在进入舞池前排队等候。领导到达时,会检查是否有追随者在等待。如果是这样,他们都可以继续。否则它会等待。同样,当追随者到达时,它会检查领导者,并相应地收益或等待。此外,还有一个限制,即每个领导者可以只与一个跟随者同时调用舞蹈,反之亦然。 书中提到它是使用信号量的解决方案,但我试图用Java中的对象锁来解决它。这里是我的解决方案: ExclusiveQueuePrimitive.java: import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ExclusiveQueuePrimitive { public static void main(String[] args) throws InterruptedException { System.out .println("-------------------------------Application START-------------------"); final int NUM_RUN = 1000; // for (int j=0; j<NUM_RUN; j++) { for (;;) { Counters c = new Counters(); int NUM_THREADS = 5; List<Thread> threads = new ArrayList<Thread>(); for (int i = 0; i < NUM_THREADS; i++) { Thread tl = new Thread(new Leader(c, i + 1)); Thread tf = new Thread(new Follower(c, i + 1)); threads.add(tf); threads.add(tl); tf.start(); tl.start(); } for (int i = 0; i < threads.size(); i++) { Thread t = threads.get(i); t.join(); } } // System.out.println("--------------------------------Application END-------------------"); } } class Counters { public int leaders = 0; public int followers = 0; //public final Lock countMutex = new ReentrantLock(); public boolean printed = false; public Lock printLock = new ReentrantLock(); public final Lock leaderQueue = new ReentrantLock(); public final Lock followerQueue = new ReentrantLock(); public void dance(String str) { System.out.println("" + str); } public void printLine() { System.out.println(""); } } class Leader implements Runnable { final Counters c; final int num; public Leader(Counters counters, int num) { this.c = counters; this.num = num; } @Override public void run() { synchronized (c.leaderQueue) { try { if (c.followers > 0) { c.followers--; synchronized (c.followerQueue) { c.followerQueue.notify(); } } else { c.leaders++; c.leaderQueue.wait(); } c.dance("Leader " + num + " called dance"); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Follower implements Runnable { final Counters c; final int num; public Follower(Counters counters, int num) { this.c = counters; this.num = num; } @Override public void run() { synchronized (c.followerQueue) { try { if (c.leaders > 0) { synchronized (c.leaderQueue) { c.leaders--; c.leaderQueue.notify(); } } else { c.followers++; c.followerQueue.wait(); } c.dance("Follower " + num + " called dance"); } catch (InterruptedException e) { e.printStackTrace(); } } } } 但是,运行一段时间后,就挂断了电话。你能告诉我死锁在哪里,我怎么修复它。另外,我想在Leader和Follower对完成后打印一个新行。我怎样才能做到这一点?








...全文
245 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_38065391 2019-09-12
  • 打赏
  • 举报
回复

这是一个典型的僵局: class Leader { synchronized (c.leaderQueue) { ... synchronized (c.followerQueue) { ... } } } class Follower { synchronized (c.followerQueue) { ... synchronized (c.leaderQueue) { ... } } } 防止最简单的事情就是抓住以相同的顺序锁(顺便说一句使用Lock和​​在一起不是一个好习惯)。还有其他一些技术可以检测死锁,但是在任务环境中,更改算法应该更有利。 开始很简单 - 使用单一锁来使逻辑正确,然后做更聪明的事情来提高并发性而不破坏正确性。
weixin_38062043 2019-09-12
  • 打赏
  • 举报
回复

你在c.followerQueue上有一个互斥体,在c.leaderQueue上有一个互斥体。一方面你首先获得领导者队列,然后获得追随者队列,另一方面你首先获得追随者队列。 这很糟糕。如果一侧抓住从动锁,另一侧抓住导向锁,则两者都不能继续。您必须避免锁定采购的顺序不一致。 要在每对完成后打印一行,只需在领导者或跟随者中打印,但不能同时打印。为领导整理的代码意味着追随者已经完成也...

433

社区成员

发帖
与我相关
我的任务
社区描述
其他技术讨论专区
其他 技术论坛(原bbs)
社区管理员
  • 其他技术讨论专区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧