Is there a Mutex in Java?

2019-01-05 08:58发布

Is there a Mutex object in java or a way to create one? I am asking because a Semaphore object initialized with 1 permit does not help me. Think of this case:

try {
   semaphore.acquire();
   //do stuff
   semaphore.release();
} catch (Exception e) {
   semaphore.release();
}

if an exception happens at the first acquire, the release in the catch block will increase the permits, and the semaphore is no longer a binary semaphore.

Will the correct way be?

try {
   semaphore.acquire();
   //do stuff
} catch (Exception e) {
   //exception stuff
} finally {
   semaphore.release();
}

Will the above code ensure that the semaphore will be binary?

8条回答
我只想做你的唯一
2楼-- · 2019-01-05 09:02

No one has clearly mentioned this, but this kind of pattern is usually not suited for semaphores. The reason is that any thread can release a semaphore, but you usually only want the owner thread that originally locked to be able to unlock. For this use case, in Java, we usually use ReentrantLocks, which can be created like this:

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

private final Lock lock = new ReentrantLock(true);

And the usual design pattern of usage is:

  lock.lock();
  try {
      // do something
  } catch (Exception e) {
      // handle the exception
  } finally {
      lock.unlock();
  }

Here is an example in the java source code where you can see this pattern in action.

Reentrant locks have the added benefit of supporting fairness.

Use semaphores only if you need non-ownership-release semantics.

查看更多
叛逆
3楼-- · 2019-01-05 09:06

See this page: http://www.oracle.com/technetwork/articles/javase/index-140767.html

It has a slightly different pattern which is (I think) what you are looking for:

try {
  mutex.acquire();
  try {
    // do something
  } finally {
    mutex.release();
  }
} catch(InterruptedException ie) {
  // ...
}

In this usage, you're only calling release() after a successful acquire()

查看更多
Luminary・发光体
4楼-- · 2019-01-05 09:06

I think you should try with :

While Semaphore initialization :

Semaphore semaphore = new Semaphore(1, true);

And in your Runnable Implementation

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

} 
catch (Exception e) 
{
// Logging
}
finally
{
   semaphore.release(1);
}
查看更多
等我变得足够好
5楼-- · 2019-01-05 09:11

To ensure that a Semaphore is binary you just need to make sure you pass in the number of permits as 1 when creating the semaphore. The Javadocs have a bit more explanation.

查看更多
Melony?
6楼-- · 2019-01-05 09:19

Mistake in original post is acquire() call set inside the try loop. Here is a correct approach to use "binary" semaphore (Mutex):

semaphore.acquire();
try {
   //do stuff
} catch (Exception e) {
   //exception stuff
} finally {
   semaphore.release();
}
查看更多
We Are One
7楼-- · 2019-01-05 09:26
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();
查看更多
登录 后发表回答