Skip to content

Commit

Permalink
Added semaphore examples
Browse files Browse the repository at this point in the history
  • Loading branch information
diegoramosb committed Oct 5, 2018
1 parent da82965 commit d4c7cc1
Show file tree
Hide file tree
Showing 9 changed files with 367 additions and 0 deletions.
35 changes: 35 additions & 0 deletions Concurrency/Semaphores/java/Semaphores/Semaphore.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package Semaphores;

/**
* Although java.util.concurrent has its own semaphore class, this is a simpler implementation of a semaphore
*/
public class Semaphore {

/**
* Semaphore's count, it represent how many threads can access the resource at the same time
*/
private int count;

public Semaphore(int count) {
this.count = count;
}

public synchronized void acquire() {
count--;
if(count < 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public synchronized void release() {
count++;
if(count <= 0) {
notify();
}
}

}
37 changes: 37 additions & 0 deletions Concurrency/Semaphores/java/Semaphores/multiplex/Multiplex.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package Semaphores.multiplex;

import Semaphores.Semaphore;

public class Multiplex {

static Semaphore semaphore;

public static void main(String args[]) {
new Multiplex();
MultiplexThread[] threads = new MultiplexThread[50];
for(int i = 0; i < threads.length; i++){
threads[i] = new MultiplexThread();
}
for(MultiplexThread thread : threads) {
thread.start();
}
}

public Multiplex() {
//This semaphore ensures that a maximum of three threads are using the resource at the same time
semaphore = new Semaphore(3);
}

/**
* You want to limit access to this method with the semaphore
*/
public static void a() {
try {
System.out.println("calling a");
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package Semaphores.multiplex;

public class MultiplexThread extends Thread {

public MultiplexThread() {
}

public void run() {
//Before calling the method, the thread acquires the permit, after calling it, it releases it.
Multiplex.semaphore.acquire();
Multiplex.a();
Multiplex.semaphore.release();
}
}
61 changes: 61 additions & 0 deletions Concurrency/Semaphores/java/Semaphores/mutex/Mutex.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package Semaphores.mutex;

import Semaphores.Semaphore;

public class Mutex {

/**
* This is the resource you want to limit access to
*/
private static int n;

static Semaphore semaphore;

public static void main(String[] args) {

new Mutex();
MutexThread a = new MutexThread(10, MutexThread.TYPE_A);
MutexThread b = new MutexThread(10, MutexThread.TYPE_B);

//This starts the two threads randomly every time you run the program
int order = (int) (Math.random() * 100) % 2;

if (order == 0) {
System.out.println("A starts");
a.start();
b.start();
} else {
System.out.println("B starts");
b.start();
a.start();
}
}

public Mutex() {
n = 0;
semaphore = new Semaphore(1); //A mutex semaphore always has a count of 1
}

//Methods a and b operate the variable in different ways

public static void a() {
n += 1000;
try {
System.out.println(n);
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public static void b() {
n ++;
try {
System.out.println(n);
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
36 changes: 36 additions & 0 deletions Concurrency/Semaphores/java/Semaphores/mutex/MutexThread.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package Semaphores.mutex;

public class MutexThread extends Thread {

private int times;

private int type;

public final static int TYPE_A = 1;

public final static int TYPE_B = 0;


public MutexThread(int veces, int llamar ) {
this.times = veces;
this.type = llamar;
}

public void run() {
if(type == TYPE_A) {
for(int i = 0; i < times; i++){
Mutex.semaphore.acquire();
Mutex.a();
Mutex.semaphore.release();
}
}
if(type == TYPE_B) {
for(int i = 0; i < times; i++){
Mutex.semaphore.acquire();
Mutex.b();
Mutex.semaphore.release();
}
}
}

}
60 changes: 60 additions & 0 deletions Concurrency/Semaphores/java/Semaphores/rendezVouz/RendezVouz.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package Semaphores.rendezVouz;

import Semaphores.Semaphore;

/**
* You use semaphores this way when you want methods in different threads to happen in a certain order
*/
public class RendezVouz {

/**
* In the end, n = ((3*8) + (4*7))/2 = 26
*/
private static int n;

static Semaphore s1;

static Semaphore s2;


public static void main(String args[]) {
new RendezVouz();
RendezVouzThread a = new RendezVouzThread(RendezVouzThread.TYPE_A);
RendezVouzThread b = new RendezVouzThread(RendezVouzThread.TYPE_B);

int order = (int) (Math.random() * 100) % 2;
if (order == 0) {
System.out.println("B starts");
a.start();
b.start();
} else {
System.out.println("A starts");
b.start();
a.start();
}
}

public RendezVouz() {
n = 0;
//In this case, semaphores start in 0, you want them to lock the first thread that calls acquire()
s1 = new Semaphore(0);
s2 = new Semaphore(0);
}

public static void xA() {
n += 3*8;
}

public static void xB() {
n += 4*7;
}

public static void yA() {
System.out.println(n);
}

public static void yB() {
n = n/2;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package Semaphores.rendezVouz;

public class RendezVouzThread extends Thread {

private int type;

public final static int TYPE_A = 1;

public final static int TYPE_B = 0;

public RendezVouzThread(int type ) {
this.type = type;
}


@Override
public void run() {
/*
* xA() and xB() can be called in any order, so each threads calls the one it corresponds to them first. Then,
* one of the thread calls release() on one of the semaphores, so when the other one calls acquire() it doesn't
* block. Then, the first thread calls acquire() on the other semaphore to wait for the other thread. Finally,
* the second thread calls release() on the semaphore that the firs thread is blocked. This way, yB() is always
* called before yA(). Independently of the order that the threads started
*/
if(type == TYPE_A){
RendezVouz.xA();
RendezVouz.s1.release();
RendezVouz.s2.acquire();
RendezVouz.yA();
}
else if(type == TYPE_B){
RendezVouz.xB();
RendezVouz.s1.acquire();
RendezVouz.yB();
RendezVouz.s2.release();
}
}

}
59 changes: 59 additions & 0 deletions Concurrency/Semaphores/java/Semaphores/signaling/Signaling.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package Semaphores.signaling;

import Semaphores.Semaphore;

/**
* You can also use semaphores when you have a method that you always want to call before another.
*/
public class Signaling {

public static double n;

static Semaphore semaphore;

public static void main(String[] args) {

new Signaling();
SignalingThread a = new SignalingThread(SignalingThread.TYPE_A);
SignalingThread b = new SignalingThread(SignalingThread.TYPE_B);

int orden = (int) (Math.random() * 100) % 2;

if (orden == 0) {
System.out.println("A starts");
a.start();
b.start();
} else {
System.out.println("B starts");
b.start();
a.start();
}

}

public Signaling() {
n = 0;
semaphore = new Semaphore(0); //You want the first thread to call acquire() to block;
}

//In this case, you always want a to be called before b to avoid getting an exception.

public static void a() {
n = 2;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

public static void b() {
System.out.println(0 / n);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package Semaphores.signaling;

public class SignalingThread extends Thread {

private int type;

public final static int TYPE_A = 1;

public final static int TYPE_B = 0;

public SignalingThread(int tipo) {
this.type = tipo;
}

public void run() {
//As you always want a() to be called first, the thread that calls it releases the permit after calling a.
if(type == TYPE_A) {
Signaling.a();
Signaling.semaphore.release();
}
if(type == TYPE_B) {
Signaling.semaphore.acquire();
Signaling.b();
}
}
}

0 comments on commit d4c7cc1

Please sign in to comment.