Java 在不同的线程上锁定和解锁
Java lock and unlock on different thread
我有一个主线程和一个辅助线程。主线程将任务添加到队列中,工作线程将它们用于计算数据。在将对象放入队列之前,我在任务对象内的 ReentrantLock 对象(在主线程)上调用了锁。当工作线程完成处理队列中的任务时,我调用解锁(在工作线程上)。问题是我得到一个 IllegalMonitorStateException 因为我在不同的线程上调用锁定和解锁。
我正在寻找可以在不同线程上执行此操作的替代锁定系统。
示例:
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);
}
}
根据问题,设计多线程应用程序的方式看起来不正确。
工作线程应该处理对象的创建,或者您应该将不可变对象传递给工作线程,工作线程完成后,它可以将结果传回主线程。
我认为在一个线程中获取锁并在另一个线程中解锁是不可能的。
您不需要备用锁系统。 ConcurrentLinkedQueue 数据结构已经提供了自己的锁系统并保证线程安全。不需要任何额外的锁定。
但是你在这里重新发明了轮子。我建议您看看 ExecutorService and ThreadPools。虽然自己构建东西是一种很好的学习体验。它也是错误的一大来源。
ExecutorService workerPool = Executors.newFixedThreadPool(10); // 10 worker threads
...
Runnable myTask = ...;
workerPool.submit(myTask); // called from the main thread
...
为什么不使用只有一个许可证的 Semaphore?您获得的不是锁定操作,而是单一许可。您应该始终使用 release() 释放锁。
我有一个主线程和一个辅助线程。主线程将任务添加到队列中,工作线程将它们用于计算数据。在将对象放入队列之前,我在任务对象内的 ReentrantLock 对象(在主线程)上调用了锁。当工作线程完成处理队列中的任务时,我调用解锁(在工作线程上)。问题是我得到一个 IllegalMonitorStateException 因为我在不同的线程上调用锁定和解锁。
我正在寻找可以在不同线程上执行此操作的替代锁定系统。
示例:
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);
}
}
根据问题,设计多线程应用程序的方式看起来不正确。
工作线程应该处理对象的创建,或者您应该将不可变对象传递给工作线程,工作线程完成后,它可以将结果传回主线程。
我认为在一个线程中获取锁并在另一个线程中解锁是不可能的。
您不需要备用锁系统。 ConcurrentLinkedQueue 数据结构已经提供了自己的锁系统并保证线程安全。不需要任何额外的锁定。
但是你在这里重新发明了轮子。我建议您看看 ExecutorService and ThreadPools。虽然自己构建东西是一种很好的学习体验。它也是错误的一大来源。
ExecutorService workerPool = Executors.newFixedThreadPool(10); // 10 worker threads
...
Runnable myTask = ...;
workerPool.submit(myTask); // called from the main thread
...
为什么不使用只有一个许可证的 Semaphore?您获得的不是锁定操作,而是单一许可。您应该始终使用 release() 释放锁。