Skip to content

Commit d4c7cc1

Browse files
committed
Added semaphore examples
1 parent da82965 commit d4c7cc1

File tree

9 files changed

+367
-0
lines changed

9 files changed

+367
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package Semaphores;
2+
3+
/**
4+
* Although java.util.concurrent has its own semaphore class, this is a simpler implementation of a semaphore
5+
*/
6+
public class Semaphore {
7+
8+
/**
9+
* Semaphore's count, it represent how many threads can access the resource at the same time
10+
*/
11+
private int count;
12+
13+
public Semaphore(int count) {
14+
this.count = count;
15+
}
16+
17+
public synchronized void acquire() {
18+
count--;
19+
if(count < 0) {
20+
try {
21+
wait();
22+
} catch (InterruptedException e) {
23+
e.printStackTrace();
24+
}
25+
}
26+
}
27+
28+
public synchronized void release() {
29+
count++;
30+
if(count <= 0) {
31+
notify();
32+
}
33+
}
34+
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package Semaphores.multiplex;
2+
3+
import Semaphores.Semaphore;
4+
5+
public class Multiplex {
6+
7+
static Semaphore semaphore;
8+
9+
public static void main(String args[]) {
10+
new Multiplex();
11+
MultiplexThread[] threads = new MultiplexThread[50];
12+
for(int i = 0; i < threads.length; i++){
13+
threads[i] = new MultiplexThread();
14+
}
15+
for(MultiplexThread thread : threads) {
16+
thread.start();
17+
}
18+
}
19+
20+
public Multiplex() {
21+
//This semaphore ensures that a maximum of three threads are using the resource at the same time
22+
semaphore = new Semaphore(3);
23+
}
24+
25+
/**
26+
* You want to limit access to this method with the semaphore
27+
*/
28+
public static void a() {
29+
try {
30+
System.out.println("calling a");
31+
Thread.sleep(500);
32+
} catch (InterruptedException e) {
33+
e.printStackTrace();
34+
}
35+
}
36+
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package Semaphores.multiplex;
2+
3+
public class MultiplexThread extends Thread {
4+
5+
public MultiplexThread() {
6+
}
7+
8+
public void run() {
9+
//Before calling the method, the thread acquires the permit, after calling it, it releases it.
10+
Multiplex.semaphore.acquire();
11+
Multiplex.a();
12+
Multiplex.semaphore.release();
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package Semaphores.mutex;
2+
3+
import Semaphores.Semaphore;
4+
5+
public class Mutex {
6+
7+
/**
8+
* This is the resource you want to limit access to
9+
*/
10+
private static int n;
11+
12+
static Semaphore semaphore;
13+
14+
public static void main(String[] args) {
15+
16+
new Mutex();
17+
MutexThread a = new MutexThread(10, MutexThread.TYPE_A);
18+
MutexThread b = new MutexThread(10, MutexThread.TYPE_B);
19+
20+
//This starts the two threads randomly every time you run the program
21+
int order = (int) (Math.random() * 100) % 2;
22+
23+
if (order == 0) {
24+
System.out.println("A starts");
25+
a.start();
26+
b.start();
27+
} else {
28+
System.out.println("B starts");
29+
b.start();
30+
a.start();
31+
}
32+
}
33+
34+
public Mutex() {
35+
n = 0;
36+
semaphore = new Semaphore(1); //A mutex semaphore always has a count of 1
37+
}
38+
39+
//Methods a and b operate the variable in different ways
40+
41+
public static void a() {
42+
n += 1000;
43+
try {
44+
System.out.println(n);
45+
Thread.sleep(50);
46+
} catch (InterruptedException e) {
47+
e.printStackTrace();
48+
}
49+
}
50+
51+
public static void b() {
52+
n ++;
53+
try {
54+
System.out.println(n);
55+
Thread.sleep(50);
56+
} catch (InterruptedException e) {
57+
e.printStackTrace();
58+
}
59+
}
60+
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package Semaphores.mutex;
2+
3+
public class MutexThread extends Thread {
4+
5+
private int times;
6+
7+
private int type;
8+
9+
public final static int TYPE_A = 1;
10+
11+
public final static int TYPE_B = 0;
12+
13+
14+
public MutexThread(int veces, int llamar ) {
15+
this.times = veces;
16+
this.type = llamar;
17+
}
18+
19+
public void run() {
20+
if(type == TYPE_A) {
21+
for(int i = 0; i < times; i++){
22+
Mutex.semaphore.acquire();
23+
Mutex.a();
24+
Mutex.semaphore.release();
25+
}
26+
}
27+
if(type == TYPE_B) {
28+
for(int i = 0; i < times; i++){
29+
Mutex.semaphore.acquire();
30+
Mutex.b();
31+
Mutex.semaphore.release();
32+
}
33+
}
34+
}
35+
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package Semaphores.rendezVouz;
2+
3+
import Semaphores.Semaphore;
4+
5+
/**
6+
* You use semaphores this way when you want methods in different threads to happen in a certain order
7+
*/
8+
public class RendezVouz {
9+
10+
/**
11+
* In the end, n = ((3*8) + (4*7))/2 = 26
12+
*/
13+
private static int n;
14+
15+
static Semaphore s1;
16+
17+
static Semaphore s2;
18+
19+
20+
public static void main(String args[]) {
21+
new RendezVouz();
22+
RendezVouzThread a = new RendezVouzThread(RendezVouzThread.TYPE_A);
23+
RendezVouzThread b = new RendezVouzThread(RendezVouzThread.TYPE_B);
24+
25+
int order = (int) (Math.random() * 100) % 2;
26+
if (order == 0) {
27+
System.out.println("B starts");
28+
a.start();
29+
b.start();
30+
} else {
31+
System.out.println("A starts");
32+
b.start();
33+
a.start();
34+
}
35+
}
36+
37+
public RendezVouz() {
38+
n = 0;
39+
//In this case, semaphores start in 0, you want them to lock the first thread that calls acquire()
40+
s1 = new Semaphore(0);
41+
s2 = new Semaphore(0);
42+
}
43+
44+
public static void xA() {
45+
n += 3*8;
46+
}
47+
48+
public static void xB() {
49+
n += 4*7;
50+
}
51+
52+
public static void yA() {
53+
System.out.println(n);
54+
}
55+
56+
public static void yB() {
57+
n = n/2;
58+
}
59+
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package Semaphores.rendezVouz;
2+
3+
public class RendezVouzThread extends Thread {
4+
5+
private int type;
6+
7+
public final static int TYPE_A = 1;
8+
9+
public final static int TYPE_B = 0;
10+
11+
public RendezVouzThread(int type ) {
12+
this.type = type;
13+
}
14+
15+
16+
@Override
17+
public void run() {
18+
/*
19+
* xA() and xB() can be called in any order, so each threads calls the one it corresponds to them first. Then,
20+
* one of the thread calls release() on one of the semaphores, so when the other one calls acquire() it doesn't
21+
* block. Then, the first thread calls acquire() on the other semaphore to wait for the other thread. Finally,
22+
* the second thread calls release() on the semaphore that the firs thread is blocked. This way, yB() is always
23+
* called before yA(). Independently of the order that the threads started
24+
*/
25+
if(type == TYPE_A){
26+
RendezVouz.xA();
27+
RendezVouz.s1.release();
28+
RendezVouz.s2.acquire();
29+
RendezVouz.yA();
30+
}
31+
else if(type == TYPE_B){
32+
RendezVouz.xB();
33+
RendezVouz.s1.acquire();
34+
RendezVouz.yB();
35+
RendezVouz.s2.release();
36+
}
37+
}
38+
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package Semaphores.signaling;
2+
3+
import Semaphores.Semaphore;
4+
5+
/**
6+
* You can also use semaphores when you have a method that you always want to call before another.
7+
*/
8+
public class Signaling {
9+
10+
public static double n;
11+
12+
static Semaphore semaphore;
13+
14+
public static void main(String[] args) {
15+
16+
new Signaling();
17+
SignalingThread a = new SignalingThread(SignalingThread.TYPE_A);
18+
SignalingThread b = new SignalingThread(SignalingThread.TYPE_B);
19+
20+
int orden = (int) (Math.random() * 100) % 2;
21+
22+
if (orden == 0) {
23+
System.out.println("A starts");
24+
a.start();
25+
b.start();
26+
} else {
27+
System.out.println("B starts");
28+
b.start();
29+
a.start();
30+
}
31+
32+
}
33+
34+
public Signaling() {
35+
n = 0;
36+
semaphore = new Semaphore(0); //You want the first thread to call acquire() to block;
37+
}
38+
39+
//In this case, you always want a to be called before b to avoid getting an exception.
40+
41+
public static void a() {
42+
n = 2;
43+
try {
44+
Thread.sleep(500);
45+
} catch (InterruptedException e) {
46+
e.printStackTrace();
47+
}
48+
}
49+
50+
public static void b() {
51+
System.out.println(0 / n);
52+
try {
53+
Thread.sleep(500);
54+
} catch (InterruptedException e) {
55+
e.printStackTrace();
56+
}
57+
}
58+
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package Semaphores.signaling;
2+
3+
public class SignalingThread extends Thread {
4+
5+
private int type;
6+
7+
public final static int TYPE_A = 1;
8+
9+
public final static int TYPE_B = 0;
10+
11+
public SignalingThread(int tipo) {
12+
this.type = tipo;
13+
}
14+
15+
public void run() {
16+
//As you always want a() to be called first, the thread that calls it releases the permit after calling a.
17+
if(type == TYPE_A) {
18+
Signaling.a();
19+
Signaling.semaphore.release();
20+
}
21+
if(type == TYPE_B) {
22+
Signaling.semaphore.acquire();
23+
Signaling.b();
24+
}
25+
}
26+
}

0 commit comments

Comments
 (0)