Java 锁定资源的时间不确定

Java 锁定资源的时间不确定,java,locking,Java,Locking,我的应用程序包含许多包含getter和setter的对象。这些对应于改变物理对象(例如,步进电机)的状态。 其他线程可能会调用此对象上的方法,以便对步进电机执行操作-这提供了步进电机和底层硬件之间的接口。例如,我们可能有一个功能,使电机旋转15度,或者我们可能有一个功能,使电机返回到空档位置 现在,这些对象关心线程安全,但这还不够好。考虑一个线程试图将电机旋转90度(通过六个呼叫旋转15度)和一半通过的情况,另一个重置电机,这意味着它只移动了45度。 我的设计解决方案是允许控制对象解除控制器上的

我的应用程序包含许多包含getter和setter的对象。这些对应于改变物理对象(例如,步进电机)的状态。 其他线程可能会调用此对象上的方法,以便对步进电机执行操作-这提供了步进电机和底层硬件之间的接口。例如,我们可能有一个功能,使电机旋转15度,或者我们可能有一个功能,使电机返回到空档位置

现在,这些对象关心线程安全,但这还不够好。考虑一个线程试图将电机旋转90度(通过六个呼叫旋转15度)和一半通过的情况,另一个重置电机,这意味着它只移动了45度。 我的设计解决方案是允许控制对象解除控制器上的锁,但我不确定如何管理它。似乎大多数Java锁定方法都设计为在单个方法调用上是原子的,我希望在不确定的时间内锁定对象


一个简单的Java锁就足够了吗,或者有人知道更好的东西吗?我担心的是,标准的ReentrantLock似乎几乎需要try-finally范式,这意味着我可能会在某种程度上对其进行屏蔽。

您可以提供一种方法,以原子方式提交多个命令。假设您的所有方法都是同步的,它可以是:

public synchronized void submitAtomically(List<Command> commands) {
    for (Command c : commands) {
        submit(c);
    }
}

public synchronized void submit(Command c) {
    //rotate or reset or ...
}
public以提交方式同步作废(列出命令){
for(命令c:命令){
提交(c);
}
}
公共同步作废提交(命令c){
//旋转或重置或。。。
}
如果不希望这些方法阻止其他线程太长时间,最简单的方法是使用典型的生产者/共同消费者模式:

private final BlockingQueue<Command> queue = new LinkedBlockingQueue<> ();

public synchronized void submit(Command c) {
    queue.put(c);
}    

//somewhere else:

new Thread(new Runnable() {
    public void run() {
        while(true) {
            Command c = queue.take();
            c.execute();
        }
    }
}).start();
private final BlockingQueue=new LinkedBlockingQueue();
公共同步作废提交(命令c){
队列。put(c);
}    
//其他地方:
新线程(newrunnable()){
公开募捐{
while(true){
命令c=queue.take();
c、 执行();
}
}
}).start();

如果一个客户端通过<代码>提交了6个旋转,则在其他6个旋转的中间,阻止其他线程插入其他命令。但是,

submit
操作非常快(它实际上并不执行命令),因此它不会长时间阻塞其他线程。

在数据库世界中,这是通过事务来完成的,事务是将小的低级操作分组为大的高级原子操作的一种方式。沿着那条路走下去会很痛苦

我认为你需要回去决定什么是基本的原子操作

考虑这样一种情况:一个线程尝试将电机旋转90度(通过启动六个调用以旋转15度),中途另一个线程重置电机,这意味着它只移动了45度

似乎您已经决定“旋转15度”是唯一的原子操作,但这显然不适合您的应用程序

  • 你是否也需要“旋转45度”和“旋转90度”作为原子操作?也许你需要“旋转X度”作为一个原子操作

  • 将电机旋转到特定位置的目的是什么?如果螺纹A将电机旋转到位置X,然后螺纹B立即将其旋转到另一个位置,那么实现了什么?一旦电机处于位置X,是否需要(通过螺纹A)执行某些操作?如果是这样,您希望旋转和该操作一起成为一个原子操作

  • 为什么在执行操作之前要将电机旋转给定的量?在执行操作时,您是否确实希望电机处于特定位置(绝对位置,而不是相对于其先前位置)?在这种情况下,您不希望您的操作被赋予旋转的量,而是所需的位置。原子操作将负责决定电机旋转多少


您如何知道电机何时完成旋转并可以发送另一个命令,是否仅基于计时?遗憾的是,这不太有效/不是我想要的。例如,一个更高级别的功能可能是:将锁重置为零,然后如果用户按下按钮,则每3分钟旋转360度。这将简单地阻塞线程,这将是无用的。我可以异步操作,但这会增加复杂性。恐怕我用步进电机作为一个简单的例子,因为我实际使用的设备是商业敏感的(与步进电机无关)。假设我的原子操作实际上是尽可能低的,我只是想说明一下。很明显,在现实生活中使用步进机时,你会做得不同。