-
Notifications
You must be signed in to change notification settings - Fork 311
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
da82965
commit d4c7cc1
Showing
9 changed files
with
367 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
37
Concurrency/Semaphores/java/Semaphores/multiplex/Multiplex.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} | ||
|
||
} |
14 changes: 14 additions & 0 deletions
14
Concurrency/Semaphores/java/Semaphores/multiplex/MultiplexThread.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
36
Concurrency/Semaphores/java/Semaphores/mutex/MutexThread.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
60
Concurrency/Semaphores/java/Semaphores/rendezVouz/RendezVouz.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
|
||
} |
39 changes: 39 additions & 0 deletions
39
Concurrency/Semaphores/java/Semaphores/rendezVouz/RendezVouzThread.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
59
Concurrency/Semaphores/java/Semaphores/signaling/Signaling.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} | ||
|
||
} |
26 changes: 26 additions & 0 deletions
26
Concurrency/Semaphores/java/Semaphores/signaling/SignalingThread.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} | ||
} |