Java中有Mutex吗?

Noa*_*evo 106 java mutex semaphore java.util.concurrent concurrent-programming

在java中是否存在Mutex对象或创建一个?我问,因为用1许可证初始化的信号量对象对我没有帮助.想想这个案例:

try {
   semaphore.acquire();
   //do stuff
   semaphore.release();
} catch (Exception e) {
   semaphore.release();
}
Run Code Online (Sandbox Code Playgroud)

如果在第一次获取时发生异常,则catch块中的释放将增加许可,并且信号量不再是二进制信号量.

请问是正确的方法吗?

try {
   semaphore.acquire();
   //do stuff
} catch (Exception e) {
   //exception stuff
} finally {
   semaphore.release();
}
Run Code Online (Sandbox Code Playgroud)

上面的代码会确保信号量是二进制的吗?

cas*_*nca 129

Java中的任何对象都可以用作使用synchronized块的锁.当发生异常时,这也将自动解除锁定.

Object someObject = ...;

synchronized (someObject) {
  ...
}
Run Code Online (Sandbox Code Playgroud)

您可以在此处阅读更多相关信息:内部锁定和同步

  • 如果您希望以不同的方法释放锁(例如`transaction.begin(); transaction.commit()`),则不能使用synchronized关键字. (16认同)
  • @Noam:只需将代码与信号量和"synchronized"进行比较,您就会发现什么是更好的可读性,更不容易出错. (10认同)

pay*_*yne 111

请参阅此页面:http: //www.oracle.com/technetwork/articles/javase/index-140767.html

它有一个略有不同的模式,(我认为)你在寻找什么:

try {
  mutex.acquire();
  try {
    // do something
  } finally {
    mutex.release();
  }
} catch(InterruptedException ie) {
  // ...
}
Run Code Online (Sandbox Code Playgroud)

在这种用法中,您只需release()在成功后调用acquire()


小智 23

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


private final Lock _mutex = new ReentrantLock(true);

_mutex.lock();

// your protected code here

_mutex.unlock();
Run Code Online (Sandbox Code Playgroud)

  • 这种方式优于已提供的解决方案?它是如何解决原始提问者所遇到的问题的? (5认同)
  • 这是一个递归互斥锁,允许从同一个线程进行多次重新锁定,这可能会有问题.一个"真正的",基本的互斥(非递归,C++风格)一次只允许一个锁.如果你将你的行更改为`private final ReentrantLock _mutex = ...`,你可以使用[getHoldCount()](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ locks/ReentrantLock.html#getHoldCount())返回线程重新锁定的次数.(您可以应用"条件"来防止这种情况.[请参阅API](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html).) (3认同)

rou*_*ble 8

没有人明确提到这一点,但这种模式通常不适合信号量.其原因是,任何线程可以释放一个信号,但你通常只想要所有者线程最初锁定到能解开.对于这个用例,在Java中,我们通常使用ReentrantLocks,可以像这样创建:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

private final Lock lock = new ReentrantLock(true);
Run Code Online (Sandbox Code Playgroud)

通常的设计模式是:

  lock.lock();
  try {
      // do something
  } catch (Exception e) {
      // handle the exception
  } finally {
      lock.unlock();
  }
Run Code Online (Sandbox Code Playgroud)

以下是java源代码中的示例,您可以在其中看到此模式的实际应用.

折返锁具有支持公平性的额外好处.

仅在需要非所有权释放语义时才使用信号量.

  • 很高兴有人指出。对于资源互斥体的独占访问是可行的方法。二进制信号量不是互斥体,信号量应该更多地用作信号机制。 (4认同)
  • 实际上这应该是这个问题的唯一正确答案.清楚地解释信号量和互斥锁之间的差异.使用`count = 1`的信号量不是互斥锁. (3认同)

Sas*_*ant 5

我认为您应该尝试:

而信号量初始化:

Semaphore semaphore = new Semaphore(1, true);
Run Code Online (Sandbox Code Playgroud)

在你的 Runnable Implementation

try 
{
   semaphore.acquire(1);
   // do stuff

} 
catch (Exception e) 
{
// Logging
}
finally
{
   semaphore.release(1);
}
Run Code Online (Sandbox Code Playgroud)