我目前正在进行一项教育任务,我必须实现一个仅限信号量的线程安全线程池。
我在作业期间不得使用:Synchronize
wait
notify
sleep
或任何线程安全的API。
首先没有太多关注我的代码:
ConcurrentLinkedQueue
测试了这个问题并且问题仍然存在)设计本身:
共享:
Tasks
信号量= 0
Available
信号量= 0
Tasks_Queue
队列
Available_Queue
队列
工作人员主题:
Blocked
信号量= 0 一般信息:
只有经理(单线程)可以出列Tasks_Queue
和Available_Queue
只有App-Main(单线程)可以排队任务Tasks_Queue
每个工作线程都可以在Available_Queue
所以我们混合了一个单一的生产者,一个经理和几个消费者。
Available_Queue
中排队,释放Available
信号量并被阻止获取它的个人Blocked
信号量。Task
信号量Tasks
和Available
信号量。我的问题:
在应用程序的运行时期间,函数dequeue_worker()
返回一个空工作符,即使知道没有可用的工作线程,也会放置一个信号量来保护对队列的访问。
我已经通过递归调用dequeue_worker()
来解决问题,如果它绘制了一个空线程,但这样做是为了让获取信号量许可永久丢失。然而,当我将工人数量限制为1时,工人不会永远被阻止。
1)我的原创设计的突破点是什么?
2)为什么我的“解决方案”不能进一步打破设计?!
代码段:
// only gets called by Worker threads: enqueue_worker(this);
private void enqueue_worker(Worker worker) {
available_queue.add(worker);
available.release();
}
// only gets called by App-Main (a single thread)
public void enqueue_task(Query query) {
tasks_queue.add(query);
tasks.release();
}
// only gets called by Manager(a single Thread)
private Worker dequeue_worker() {
Worker worker = null;
try {
available.acquire();
worker = available_queue.poll();
} catch (InterruptedException e) {
// shouldn't happen
} // **** the solution: ****
if (worker==null) worker = dequeue_worker(); // TODO: find out why
return worker;
}
// only gets called by Manager(a single Thread)
private Query dequeue_task() {
Query query = null;
try {
tasks.acquire();
query = tasks_queue.poll();
} catch (InterruptedException e) {
// shouldn't happen
}
return query;
}
// gets called by Manager (a single thread)
private void execute() { // check if task is available and executes it
Worker worker = dequeue_worker(); // available.down()
Query query = dequeue_task(); //task.down()
worker.setData(query);
worker.blocked.release();
}
最后是工人的Run()
方法:
while (true) { // main infinite loop
enqueue_worker(this);
acquire(); // blocked.acquire();
<C.S>
available.release();
}
答案 0 :(得分:3)
您正在available.release()
两次,一次在enqueue_worker
,第二次在主循环中。