6

我有一个主线程和一个工作线程。主线程将任务添加到队列中,工作线程将它们带到计算数据中。在将对象放入队列之前,我在任务对象内的ReentrantLock 对象(在主线程上)上调用 lock。当工作线程完成处理队列中的任务时,我调用解锁(在工作线程上)。问题是我得到一个 IllegalMonitorStateException 因为我在不同的线程上调用 lock 和 unlock 。

我正在寻找可以在不同线程上执行此操作的替代锁定系统。

例子:

public class Worker extends Thread {
    public static Queue<Task> tasks = new ConcurrentLinkedQueue<Task>();

    @Override
    public void run() {
        while (true) {
            Task task = tasks.poll();

            if (task != null) {
                task.work();
                task.lock.unlock(); // Here is the unlock, Task#i should not change up to now
            }
        }
    }
}


public class Task {
    private int i = 0;
    public Lock lock;

    public void setI(int i) {
        lock.lock();
        this.i = i;
        lock.unlock();
    }

    public void work() {
        System.out.println(i);
    }
}


public class Test {
    Task task = new Task();

    public void addTask() {
        task.lock.lock(); // Here is the lock, Task#i should not change
        Worker.tasks.add(task);
    }
}
4

3 回答 3

8

为什么不使用只有一个许可证的信号量?您获得的不是锁定操作,而是单个许可证。您应该始终使用 release() 释放锁。

于 2018-01-19T14:56:02.803 回答
0

根据问题,设计多线程应用程序看起来不是正确的方法。

工作线程应该处理对象的创建,或者您应该将不可变对象传递给工作线程,一旦工作线程完成,它就可以将结果传递回主线程。

我认为在一个线程中获取锁定并在另一个线程中解锁是不可能的。

于 2016-04-15T17:52:03.677 回答
0

您不需要替代锁定系统。ConcurrentLinkedQueue数据结构已经提供了它自己的锁系统并保证了线程安全。任何额外的锁定都是不必要的。

但是你在这里重新发明了轮子。我建议你看看ExecutorServiceThreadPools。虽然自己构建东西是一种很好的学习体验。这也是错误的一大来源。

ExecutorService workerPool = Executors.newFixedThreadPool(10); // 10 worker threads
...
Runnable myTask = ...;
workerPool.submit(myTask); // called from the main thread
...
于 2016-04-16T10:03:14.570 回答