不同线程上的Java锁定和解锁

不同线程上的Java锁定和解锁,java,multithreading,locking,reentrantlock,Java,Multithreading,Locking,Reentrantlock,我有一个主线程和一个工作线程。主线程将任务添加到队列中,工作线程将它们用于计算数据。在将对象放入队列之前,我对任务对象内部的ReentrantLock对象(,位于主线程上)调用lock。当工作线程完成对队列中任务的处理时,我调用unlock(,在工作线程上)。问题是我得到了一个非法的MonitorStateException,因为我在不同的线程上调用了lock和unlock 我正在寻找一个替代的锁系统,我可以在不同的线程上这样做 例如: public class Worker extends T

我有一个主线程和一个工作线程。主线程将任务添加到队列中,工作线程将它们用于计算数据。在将对象放入队列之前,我对任务对象内部的ReentrantLock对象(,位于主线程上)调用lock。当工作线程完成对队列中任务的处理时,我调用unlock(,在工作线程上)。问题是我得到了一个非法的MonitorStateException,因为我在不同的线程上调用了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);
    }
}
公共类工作线程扩展{
公共静态队列任务=新建ConcurrentLinkedQueue();
@凌驾
公开募捐{
while(true){
Task=tasks.poll();
如果(任务!=null){
任务。工作();
task.lock.unlock();//这是解锁,task#我现在还不应该更改
}
}
}
}
公开课任务{
私有整数i=0;
门锁;
公共无效setI(int i){
lock.lock();
这个。i=i;
lock.unlock();
}
公共工程(){
系统输出打印LN(i);
}
}
公开课考试{
任务=新任务();
公共void addTask(){
task.lock.lock();//这是锁,task#我不应该改变
Worker.tasks.add(任务);
}
}

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

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


我认为在一个线程中获得锁,在另一个线程中解锁是不可能的。

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

但你在这里重新发明轮子。我建议你看一看,然后。虽然这是一个很好的学习经验,建立自己的东西。它也是bug的一大来源

ExecutorService workerPool = Executors.newFixedThreadPool(10); // 10 worker threads
...
Runnable myTask = ...;
workerPool.submit(myTask); // called from the main thread
...

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

您想用锁保护什么?@对象中的支柱数据。在锁定和解锁之前对对象进行同步,然后围绕该锁定进行锁定。您的锁似乎放错了位置。您可以使用
信号灯来做您想做的事情,而不是使用
可重入锁
,但是锁定一个线程并解锁另一个线程不是保护数据的有效方法。我无法重新设计应用程序。我修改一个应用程序。原始应用程序是单线程的,我想添加这个工作线程,它应该在对象添加到队列时处理对象的状态。是不是一个信号可以在一个线程中获取,在另一个线程中释放,而锁必须在同一个线程中锁定/解锁?我的应用程序是这样的:在线程1中,我使用无限循环运行works,而(true){…theLock.lock();//这是为了确保上一次运行的所有工作都已完成,然后在不同的线程中执行几项工作,所有工作都是异步的,每项工作完成后都会向主线程发送消息},在线程2中,接收到work done(已完成工作)消息,并且在所有任务完成时解锁锁。信号灯工作,但可重入锁不工作。