Java锁定简单的多线程队列类以避免饥饿

8e2ybdfx  于 2023-02-02  发布在  Java
关注(0)|答案(1)|浏览(104)

我目前正在回顾并发性,并希望再次检查我的理解。
假设我有一个简单的队列类,我想使用多个线程从队列中取出作业并运行。

class JobQueue {
    static Queue<Job> jobq;
    ExecutorService exec;

    public void addJob(Job j) 
        synchronized(jobq) {
            jobq.add(j)
        }
    
    public void runJob() {
      synchronized(jobq) {
         while (!jobq.isEmpty()) {
             exec.submit(() -> jobq.poll().run());
         }
      }
    }

请原谅我的语法,我很快把这些放在一起。无论如何,我有一个两部分的问题。
1.为了避免addJob方法的饥饿,锁定!jobq.isEmpty()然后解锁,然后单独锁定exec.submit...,这样在检查jobq为空和轮询一个作业关闭之间,addJob有机会获得锁,这是不是更好?
1.如果是上面的情况(最好在while检查之后解锁),您将如何对这个同步对象进行解锁?因为exec.submit嵌套在while循环中,而while循环又嵌套在synchronized(jobq)循环中。

rsl1atfo

rsl1atfo1#

1.为了避免addJob方法的饥饿,锁定!jobq.isEmpty()然后解锁,然后单独锁定exec.submit...,这样在检查jobq为空和轮询一个作业关闭之间,addJob有机会获得锁,这是不是更好?
在这种情况下,锁定整个while{...}循环是可以的,因为exec.submit...没有做太多事情:当任务在另一个线程中执行时,它实际上只创建并返回Future
另外,如果!jobq.isEmpty()exec.submit...分别被锁定,则会出现另一个问题:如果在这些锁之间另一个线程执行runJob()并且jobq变为空,该怎么办?

相关问题