1

Now I investigate semaphores. I googled following link about this theme:

link

Author of this link wrote about using semaphores for signaling. To show how it works he wrote custom semaphore.

custom semaphore code:

public class Semaphore {
  private boolean signal = false;

  public synchronized void take() {
    this.signal = true;
    this.notify();
  }

  public synchronized void release() throws InterruptedException{
    while(!this.signal) wait();
    this.signal = false;
  }

}

about how use it in code he wrote following:

public class SendingThread {
  Semaphore semaphore = null;

  public SendingThread(Semaphore semaphore){
    this.semaphore = semaphore;
  }

  public void run(){
    while(true){
      //do something, then signal
      this.semaphore.take();

    }
  }
}



public class RecevingThread {
  Semaphore semaphore = null;

  public ReceivingThread(Semaphore semaphore){
    this.semaphore = semaphore;
  }

  public void run(){
    while(true){
      this.semaphore.release();
      //receive signal, then do something...
    }
  }
}

main:

Semaphore semaphore = new Semaphore();

SendingThread sender = new SendingThread(semaphore);

ReceivingThread receiver = new ReceivingThread(semaphore);

receiver.start();
sender.start();

As I understood order of execution should be following

send - receive
send - receive
send - receive
...

I tryed to write own code using this bluerprint

public class SendReceiveWithCustomSemaphore {
    public static void main(String[] args) {
        MySemaphore mySemaphore = new MySemaphore();
        new Send(mySemaphore).start();
        new Receive(mySemaphore).start();
    }
}

class MySemaphore {
    boolean flag = false;

    public synchronized void take() throws InterruptedException {
        flag = true;
        notify();
    }

    public synchronized void release() throws InterruptedException {
        while (!flag) {
            wait();
        }
        flag = false;
    }
}

class Send extends Thread {
    MySemaphore mySemaphore;

    public Send(MySemaphore semaphore) {
        this.mySemaphore = semaphore;
    }

    @Override
    public void run() {
        int i = 0;
        while (i++ < 10) {
            System.out.println("send");
            try {
                mySemaphore.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Receive extends Thread {
    MySemaphore mySemaphore;

    public Receive(MySemaphore semaphore) {
        this.mySemaphore = semaphore;
    }

    @Override
    public void run() {
        while (true) {
            try {
                mySemaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("receive");
        }
    }
}

output:

send
send
send
send
send
send
send
send
send
send
receive

Thus it is not expected behaviour for me.

I made a mistake then I wrote code or I didn't understand concept ?

What did author want to say?

gstackoverflow
  • 36,709
  • 117
  • 359
  • 710

2 Answers2

4

Find a better tutorial.

The output that you see is about what I would expect. The "sender" thread never blocks, so it will go on printing "send", "send", "send" forever. Meanwhile, over in the "receiver" thread, each time it calls the semaphore.release() method, it will be blocked until the next time the sender gets to run.

I would expect to see lots of "send" messsages, with occasional "receive" messages mixed in---more or less what you describe seeing.

I don't know what that example is supposed to prove, but for me, it creates the impression that the author does not know how programmers expect Semaphores to behave.

Some authors provide examples of what not to do, or examples containing a deliberate mistake that will be "fixed" in a later example. Are you sure you are not following an example of that kind?

Edit: I followed the link, and it looks like the main problem is that the names were swapped in the definitions of the take() and release() methods. If you just switch the names, it makes more sense.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
  • please check this link – gstackoverflow Apr 23 '14 at 21:28
  • while (i++ < 10) { System.out.println("send"); – gstackoverflow Apr 23 '14 at 21:30
  • 10 - count of send messages – gstackoverflow Apr 23 '14 at 21:30
  • @gstackoverflow, I followed the link, and the information on that page is just wrong. In the last example, where he shows how to use a semaphore as a mutex, he calls semaphore.take() before entering the critical section and semaphore.release() upon leaving it. But the behavior of take() and release() are exactly the opposite of what they should be. The take() method should be the one that waits, and the release() method should be the one that notifies. In his mutex example, any number of threads can get into the critical section at the same time, but only one will ever get out of it again. – Solomon Slow Apr 23 '14 at 22:33
  • I wouldn’t even call this article a “tutorial”. It’s just a bunch of code fragments and some comments far smaller than the API documentation of the corresponding Java classes, i.e. compare it to [`Semaphore`](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html) and [`CountDownLatch`](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html) – Holger Apr 24 '14 at 08:48
1

By the time ReceiveSemafore is started SendSemafore has already executed 10 times.

Consider using a CountDownLatch to start the two threads at the same time. Although as pointed out by Fuhrmanator this will not produce the alternating output that you are looking for.

For this i would use a bounded semaphore with one signal.

maxmil
  • 390
  • 1
  • 12
  • Also, I'd argue that if you run this program multiple times, it won't always be the same number of "send" messages before receive. Even with the CountDownLatch, just because you start threads at the same time, it doesn't mean they'll execute the same way every time. I would simply introduce a `Thread.sleep(1000);` at the start of the sender to delay it (to make sure the receiver is waiting first, before it does its first send). – Fuhrmanator Apr 23 '14 at 21:53
  • @maxmil anyway code shouldn't rely on Thread.sleep(). Concept is wrong. – gstackoverflow Apr 24 '14 at 15:34