1

I have a code in here which is being used to explain how the semaphore works.. No matter How hard I try I am not understanding the line below and there by how to code semaphore is invoked.

Basically the code tries to simulate many connects being made...

import java.util.concurrent.Semaphore;

public class Connection {

    private static Connection instance = new Connection();

    private Semaphore sem = new Semaphore(10, true);

    private int connections = 0;

    private Connection() {

    }

    public static Connection getInstance() {
        return instance;
    }

    public void connect() {
        try {
            sem.acquire();
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        try {
            doConnect();
        } finally {

            sem.release();
        }
    }

    public void doConnect() {

        synchronized (this) {
            connections++;
            System.out.println("Current connections: " + connections);
        }

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        synchronized (this) {
            connections--;
        }

    }
}

Main class file..

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


public class App {

    public static void main(String[] args) throws Exception {

        ExecutorService executor = Executors.newCachedThreadPool();

        for(int i=0; i < 200; i++) {
            executor.submit(new Runnable() {
                public void run() {
                    Connection.getInstance().connect();
                }
            });
        }

        executor.shutdown();

        executor.awaitTermination(1, TimeUnit.DAYS);
    }

}

I am not understanding the run part

public void run() {
    Connection.getInstance().connect();
}

How can we call a connect method from the above? in my judgement connections output should always be one as new threads are being called. surprisingly but that never happens.

pogopaule
  • 1,533
  • 2
  • 10
  • 17
User27854
  • 824
  • 1
  • 16
  • 40
  • You might want to declare `connections` volatile to make it being atomically updated on the stack. Could you clarify your misunderstanding? You don't understand the output for the code? Could you provide what you're getting as it could be very different under circumstances for multithreaded apps? – Andrey Chaschev Dec 24 '13 at 13:30
  • The code is running fine absolutely no problem with that... I am not understanding this part.. What is it doing? public void run() { Connection.getInstance().connect(); } – User27854 Dec 24 '13 at 13:33

2 Answers2

2

Semaphore is used to acquire lock , and execute some code then finally release the lock.

In your code also same thing is happening.

  1. sem.acquire(); will acquire a lock .
  2. doConnect(); // write your code here .
  3. sem.release(); release the lock .

For more details refer this .

Sujith PS
  • 4,776
  • 3
  • 34
  • 61
2

I'll try to explain what's happening there. This code below is being run in each separate thread since you're submitting it to a thread pool:

public void run() {
    Connection.getInstance().connect();
}

Connection.getInstance() here returns a singleton (an single instance of an object Connection which is shared among threads, more: What is an efficient way to implement a singleton pattern in Java?). This singleton in it's turn contains a semaphore which is also single and is shared among the threads. So the whole purpose of this technique in this case is to share a semaphore between multiple threads.

What happens in connect():

public void connect() {
    try {
        // this acquires a single permit for a shared semaphore,
        // so no more than 10 threads (the result of new Semaphore(10, true)) 
        // will enter the critical section below simultaneously
        sem.acquire();
    } catch (InterruptedException e1) {
        e1.printStackTrace();
    }

    try {
        // the critical section, at this point there will be 10 threads at max
        // this is the purpose of the semaphore
        doConnect();
    } finally {
        // returns the permit acquired, so that a one more thread may 
        // enter the critical section
        sem.release();
    }
}
Community
  • 1
  • 1
Andrey Chaschev
  • 16,160
  • 5
  • 51
  • 68
  • Thank you Andrey for your suggestions, I had no knowledge of Singleton. I searched on net and have a slight idea of it now.. Could you please elaborate on the run method public void run() { Connection.getInstance().connect(); } – User27854 Dec 24 '13 at 14:19
  • I can direct you to the [Oracle tutorial](http://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html). There also a chapter on the executors, you might want to have a look at it. Basically, `run()` defines a thread to run and in this cases this thread is being run inside a container - a thread pool. – Andrey Chaschev Dec 24 '13 at 14:27
  • I understand that.. The thing that is troubling me is there is no method called connect inside getInstance. Then how can this work? Sorry for not being clear... – User27854 Dec 24 '13 at 14:30
  • `getInstance()` is a method which returns a singleton instance of `Connection` - a static field declared: `private static Connection instance = new Connection();`. So the `connect()` is being called on this object. It is equivalent to `Connection.instance.connect()`; – Andrey Chaschev Dec 24 '13 at 14:38
  • Thanks a lot for your time and suggestions.. I am able to get a clear picture.. Need to practice a lot... – User27854 Dec 24 '13 at 14:45