是否可以在一种方法中获取锁并从另一种方法中释放它?

发布于 2024-11-05 10:30:24 字数 414 浏览 0 评论 0原文

我基本上使用的是一个框架,它从两个不同的线程调用一堆函数。我希望在允许下一个线程继续之前完成整个线程。但是,我无法更改那里的代码。

例如,假设有两个线程:线程 1 和线程 2。每个线程调用方法一到方法三。

所以你会得到一个类似于以下的调用顺序:

T1-M1
T1-M2
T2-M1
T1-M3
T2-M2
T2-M3

但是,我希望发生的是 T1-M1 设置某种会阻止 T2 的锁,因此顺序如下。

T1-M1 - get lock
        T2-M1 - blocked
T1-M2
T1-M3 - release lock

T2-M1 - no longer blocked - gets lock
T2-M2
T2-M3

是否可以在 Java 中执行此操作,而无需编辑框架中的调用方法?

I basically I am using a frame work that calls a bunch of functions from two different threads. I would like one entire thread to complete before the next thread is allow to continue. However, I can not change there code.

For example suppose there are two threads, thread 1 and thread 2. Each thread calls methods one through three.

So you get a call order something like:

T1-M1
T1-M2
T2-M1
T1-M3
T2-M2
T2-M3

However, what I would like to have happen is T1-M1 one sets some sort of lock that will block T2, so the order will be as follows.

T1-M1 - get lock
        T2-M1 - blocked
T1-M2
T1-M3 - release lock

T2-M1 - no longer blocked - gets lock
T2-M2
T2-M3

Is it possible to do this in Java without editing the calling method from the framework?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

可爱咩 2024-11-12 10:30:24

您无法使用 synchronized 关键字提供的简单功能来做到这一点:它的锁必须在获取它的同一方法(偶数块)中释放。

您可以使用 < 中的工具但是,代码>java.util.concurrent.locks

它是 ReentrantLock 类几乎是具体化 同步机制。

但请记住,这种方法是危险的。如果线程调用 M1M2,但从不调用 M3,该怎么办?例如,在调用 M2M3 之间的某些代码中可能会出现异常。

You can't do that with the simple features provided by the synchronized keyword: its lock must be released in the same method (even block) on which it's acquired.

You can use the tools in java.util.concurrent.locks, however.

It's ReentrantLock class is pretty much a reification of the synchronized mechanism.

Bear in mind that such an approach is dangerous, however. What if a thread calls M1 and M2, but never calls M3? It might get an exception in some code between the calls to M2 and M3, for example.

腹黑女流氓 2024-11-12 10:30:24

您无法从另一个方法释放内在锁,但可以从另一个方法释放 jucLock。例如:(根据 Peter Lawrey 的回复进行编辑,谢谢)

public boolean tryAcquireTimedLock(){
    return lock.tryLock(30, TimeUnit.SECONDS);
}

public void releaseLock(){
   lock.unlock();
}

这里提供了一种在超时时中断地获取锁的便捷方法。

现在让我们来看看陷阱。如果您使用不同的方法锁定和解锁,则必须小心在此过程中可能发生的任何异常。不考虑这一点可能会导致死锁问题。

public void doSomeWork(){
    if(tryAcquireTimedLock()){

         otherMethodWork();

         finalMethodWork();
    }
}


public void otherMethodWork(){
   //do something that may cause an Exception
}

public void finalMethodWork(){
   //finish work now release lock
    releaseLock();
}

现在,如果 otherMethodWork() 抛出 RuntimeException 该怎么办?您的代码现在将永远无法调用 releaseLock() 并且无法取得更多进展。

这就是为什么指示使用样式

lock.lock();
try{
  //work
}finally{
  lock.unlock();
}

如果 //work 中发生任何错误,您仍然可以解锁并取得进展。

You cannot release an intrinsic lock from another method but you can release a j.u.c.Lock from another method. For example: (Edited based on Peter Lawrey's response, thanks)

public boolean tryAcquireTimedLock(){
    return lock.tryLock(30, TimeUnit.SECONDS);
}

public void releaseLock(){
   lock.unlock();
}

Here offers a convenience method to acquire a lock interruptbly with a timeout.

Now lets get to the pitfalls. If you lock and unlock from different method you have to be careful of any exception that can occur during the process. Failure to account for this can lead to a deadlock issue.

public void doSomeWork(){
    if(tryAcquireTimedLock()){

         otherMethodWork();

         finalMethodWork();
    }
}


public void otherMethodWork(){
   //do something that may cause an Exception
}

public void finalMethodWork(){
   //finish work now release lock
    releaseLock();
}

Now what if otherMethodWork() throws a RuntimeException? Your code will now never be able to invoke releaseLock() and no more progress can be made.

This is why it is instructed to use the style

lock.lock();
try{
  //work
}finally{
  lock.unlock();
}

If anything wrong happens in //work you will still be able to unlock and make progress.

始于初秋 2024-11-12 10:30:24

如果您不想控制来自框架层的调用,您可以通过将此逻辑设置到每个线程中来验证它们何时可以访问每个方法,您可以使用会话变量作为标志,例如控制方法何时可用于任何其他线程,因此您只需调用线程,它们将具有访问方法的验证。-

If you do not want to control the calling from the framework layer you can do it by setting this logic into every thread you have validating when they can access to every single method, you can use session variables as flags for example to control when the method is available to any other so you can just call the threads and they will have the validations to access the methods.-

趁微风不噪 2024-11-12 10:30:24

只是对其他帖子的补充,所有 3 个方法必须共享相同的锁,这里的共享资源是 3 个方法的捆绑,当 T2 已经锁定时,您不希望 T1 获得 M1 和 M2 的锁定M3。

Just a complement of the other posts, all 3 methods have to share the same lock, the shared resource here is the bundle of the 3 methods, you don't want T1 getting a lock on M1 and M2 when T2 has already a lock on M3.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文