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

时间:2011-05-05 15:50:00

标签: java multithreading locking thread-safety

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

例如假设有两个线程,线程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中执行此操作而无需编辑框架中的调用方法?

4 个答案:

答案 0 :(得分:6)

您无法使用synchronized关键字提供的简单功能执行此操作:其锁定必须以与其获取的相同方法(偶数块)发布。

但是,您可以使用java.util.concurrent.locks中的工具。

ReentrantLock类几乎是synchronized机制的reification

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

答案 1 :(得分:1)

您无法从其他方法释放内部锁定,但可以从其他方法释放j.u.c.Lock。例如:(根据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();
}

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

答案 2 :(得分:0)

如果您不想从框架层控制调用,可以通过将此逻辑设置为您可以访问每个方法时验证的每个线程来实现,您可以使用会话变量作为标志来控制当该方法可用于任何其他方法时,您可以调用线程,并且他们将具有访问方法的验证.-

答案 3 :(得分:0)

只是其他帖子的补充,所有3种方法都必须共享相同的锁,这里的共享资源是3种方法的捆绑,你不希望T1在T2已经锁定M1和M2锁定M3。