Semafori

Semafori in Java

Utilizzo dei semafori come lock per prevenire le race condition: si possono usare i semafori per bloccare (lock) l'accesso a una risorsa, ogni thread che vuole accedere all'utilizzo della risorsa deve prima chiamare la acquire() per prendere il lock. Quando il thread ha ultimato con la risorsa, deve chiamare release() per rilasciare il lock. Esempio di utilizzo di java.util.concurrent.Semaphore.

package sharedobject;

//A shared resource/class.
public class SharedObject {
    int count = 0;
}
package sharedobject;

// java program to demonstrate 
// use of semaphores Locks 

import java.util.concurrent.Semaphore;

class WorkerThread extends Thread
{ 
	Semaphore sem;
	SharedObject sharedObject;

	public WorkerThread(Semaphore sem, SharedObject sharedObject, String threadName)
	{ 
		super(threadName); 
		this.sem = sem;
		this.sharedObject = sharedObject;
	}

	@Override
	public void run() { 
		
		// run by thread A 
		if(this.getName().equals("A")) 
		{ 
			System.out.println("Starting " + getName());
			try
			{ 
				// First, get a permit. 
				System.out.println(getName() + " is waiting for a permit.");
			
				// acquiring the lock 
				sem.acquire(); 
			
				System.out.println(getName() + " gets a permit.");
		
				// Now, accessing the shared resource. 
				// other waiting threads will wait, until this 
				// thread release the lock 
				for(int i=0; i < 5; i++) 
				{ 
					sharedObject.count++;
					System.out.println(getName() + ": " + sharedObject.count);
		
					// Now, allowing a context switch -- if possible. 
					// for thread B to execute 
					Thread.sleep(10); 
				} 
			} catch (InterruptedException exc) { 
					System.out.println(exc); 
				} 
		
				// Release the permit. 
				System.out.println(getName() + " releases the permit.");
				sem.release(); 
		} 
		
		// run by thread B 
		else
		{ 
			System.out.println("Starting " + getName());
			try
			{ 
				// First, get a permit. 
				System.out.println(getName() + " is waiting for a permit.");
			
				// acquiring the lock 
				sem.acquire(); 
			
				System.out.println(getName() + " gets a permit.");
		
				// Now, accessing the shared resource. 
				// other waiting threads will wait, until this 
				// thread release the lock 
				for(int i=0; i < 5; i++) 
				{ 
					sharedObject.count--;
					System.out.println(getName() + ": " + sharedObject.count);
		
					// Now, allowing a context switch -- if possible. 
					// for thread A to execute 
					Thread.sleep(10); 
				} 
			} catch (InterruptedException exc) { 
					System.out.println(exc); 
				} 
				// Release the permit. 
				System.out.println(getName() + " releases the permit.");
				sem.release(); 
		} 
	} 
} 

// Driver class 
public class SemaphoreDemo 
{ 
	public static void main(String args[]) throws InterruptedException 
	{ 
		// creating a Semaphore object 
		// with number of permits 1 
		Semaphore sem = new Semaphore(1);
		SharedObject sharedObject = new SharedObject();
		
		// creating two threads with name A and B 
		// Note that thread A will increment the count 
		// and thread B will decrement the count 
		WorkerThread mt1 = new WorkerThread(sem, sharedObject, "A");
		WorkerThread mt2 = new WorkerThread(sem, sharedObject, "B");
		
		// stating threads A and B 
		mt1.start(); 
		mt2.start(); 
		
		// waiting for threads A and B 
		mt1.join(); 
		mt2.join(); 
		
		// count will always remain 0 after 
		// both threads will complete their execution 
		System.out.println("count: " + sharedObject.count);
	} 
} 

L'output dell'esecuzione, può essere:

Starting A
Starting B
A is waiting for a permit.
A gets a permit.
B is waiting for a permit.
A: 1
A: 2
A: 3
A: 4
A: 5
A releases the permit.
B gets a permit.
B: 4
B: 3
B: 2
B: 1
B: 0
B releases the permit.
count: 0

oppure:

Starting B
Starting A
B is waiting for a permit.
A is waiting for a permit.
B gets a permit.
B: -1
B: -2
B: -3
B: -4
B: -5
B releases the permit.
A gets a permit.
A: -4
A: -3
A: -2
A: -1
A: 0
A releases the permit.
count: 0

Vedi:

Last updated