views:

608

answers:

5

What is java's equivalent of ManualResetEvent?

+4  A: 

The closest I know of is the Semaphore. Just use it with a "permit" count of 1, and aquire/release will be pretty much the same as what you know from the ManualResetEvent.

A semaphore initialized to one, and which is used such that it only has at most one permit available, can serve as a mutual exclusion lock. This is more commonly known as a binary semaphore, because it only has two states: one permit available, or zero permits available. When used in this way, the binary semaphore has the property (unlike many Lock implementations), that the "lock" can be released by a thread other than the owner (as semaphores have no notion of ownership). This can be useful in some specialized contexts, such as deadlock recovery.

Lucero
I don't think this can work without a race condition (assuming a thread cannot release a semaphore it did not previously acquire itself)
ripper234
I take it back - from the documentation it appears a semaphore can be released without ever taking it.
ripper234
Yeah, that's because semaphores have no ownership notion. They are pretty much synchronized counters which have threads wait if the counter is 0.
Lucero
+2  A: 

Based on:

ManualResetEvent allows threads to communicate with each other by signaling. Typically, this communication concerns a task which one thread must complete before other threads can proceed.

from here:

http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx

you possibly want to look at the Barriers in the Java concurrency package - specifically CyclicBarrier I believe:

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/CyclicBarrier.html

It blocks a fixed number of threads until a particular event has occured. All the threads must come together at a barrier point.

Jon
+4  A: 

Try CountDownLatch with count of one.

CountDownLatch startSignal = new CountDownLatch(1);
crafty
A: 

I believe the crux of the .NET MRE is thread affinity and its ability to let all waiting threads go through when Set is called. I found the use of the Semaphore works well. However, if I get 10 or 15 threads waiting, then I run into another issue. Specifically, it occurs when Set is called. In .Net, all waiting threads are released. Using a semphore does not release all. So I wrapped it in a class. NOTE: I am very familiar with .NET threading. I am relatively new to Java threading and synchronization. Nevertheless, I am willing to jump in and get some real feedback. Here's my implementation with assumptions that a Java novice would make:

public class ManualEvent {
private final static int MAX_WAIT = 1000;
private final static String TAG = "ManualEvent"; 
private Semaphore semaphore = new Semaphore(MAX_WAIT, false);

private volatile boolean signaled = false;
public ManualEvent(boolean signaled) {
 this.signaled = signaled; 
 if (!signaled) {
  semaphore.drainPermits();
 }
}

public boolean WaitOne() {
 return WaitOne(Long.MAX_VALUE);
}

private volatile int count = 0;
public boolean WaitOne(long millis) {
 boolean bRc = true;
 if (signaled)
  return true;

 try {
  ++count;
  if (count > MAX_WAIT) {
   Log.w(TAG, "More requests than waits: " + String.valueOf(count));
  }

  Log.d(TAG, "ManualEvent WaitOne Entered");
  bRc = semaphore.tryAcquire(millis, TimeUnit.MILLISECONDS);
  Log.d(TAG, "ManualEvent WaitOne=" + String.valueOf(bRc));
 }
 catch (InterruptedException e) {
  bRc = false;
 }
 finally {
  --count;
 }

 Log.d(TAG, "ManualEvent WaitOne Exit");
 return bRc;
}

public void Set() {
 Log.d(TAG, "ManualEvent Set");
 signaled = true;
 semaphore.release(MAX_WAIT);
}

public void Reset() {
 signaled = false;
 //stop any new requests
 int count = semaphore.drainPermits();
 Log.d(TAG, "ManualEvent Reset: Permits drained=" + String.valueOf(count));
}

}

Also note that I am basically betting that there's no more than a 1000 requests waiting for a release at any given time. By releasing and aquiring in batches, I am attempting to release any waiting threads. Note the call to WaitOne is working 1 permit at a time.