【发布时间】:2017-08-30 18:25:43
【问题描述】:
在为工作线程使用简单的互斥量和条件变量时,我的程序会遇到一些罕见且零星的线程饥饿错误,我想防止这种情况发生。
以下是我正在做的一个简单示例。有 4 个工作线程调用“Producer”,一个主线程调用 prod.getTasks()。
此代码“无死锁”,但由于错误,显然不是“无饥饿”。
当我得到 检测到线程不足或时钟跳跃(管家 delta=1m18s317ms137µs765ns) 错误时:
A) 因为生产者线程处于等待状态的时间过长? (我不这么认为,因为我相信线程可以等待任意时间才能准备好使用。肯定超过 1 分钟)。
B) 因为其中一个等待的工作线程已被传递太多次?
基本上,任何有助于消除饥饿的好建议都会受到赞赏。
class Producer implements Runnable
{
private static ArrayList<Task> arrTasks = new ArrayList<Task>();
void getTasks()
{
Task t = getTask(); // get Tasks from a producer specific recordset.
synchronized (arrTasks)
{
arrTasks.add(t);
arrTasks.notify();
}
}
void run()
{
while (true)
{
Task t = null;
synchronized (arrTasks)
{
if (arrTasks.size() == 0)
arrTasks.wait();
if (arrTasks.size() > 0)
t = arrTasks.remove(0);
}
if (t != null)
processTask(t);
if (mExit)
break;
}
}
}
【问题讨论】:
-
代码不完整。
s_ptTasks是什么?此外,您wait()在一个对象上,notify()在另一个对象上。这样可以吗? -
@RomanPuchkovskiy:我的错……我编辑了它。
-
@NathanHughes 这是对实际代码的简化,它确实正确使用了受保护的块。我也知道我可以使用更高级别的服务来处理并发。这只是一个关于饥饿的问题。
-
你为什么不使用阻塞队列?它将为您进行同步,
ArrayBlockingQueue至少有一个带有fair选项。 (所以不会饿死单个消费者) -
我刚刚编辑了代码以更准确地表示真实代码。 Worker 实际处理一个任务,然后检查消费者是否落后,如果落后则等待。
标签: java multithreading concurrency mutex condition-variable