Watki, semafory

0

Mam taki problemik. W zasadzie wrzucam działający kod, ale chciałbym dowiedzieć się co o tym myślicie.
Problem jest taki, że mamy jakiś (ograniczony jak dodamy konsumentow, na razie tylko producenci) bufor, dajmy na to jakąś prostą kolejke zaimplementowaną na tablicy (push get isempty isfull) i teraz jak gdzies w producencie chce cos wrzucic do kolejki to:(takich producentow jest np 8)

semafor.aquire();
koleka.robCos();
semafor.release();

i teraz przechodzimy do implementacji klasy MySemaphore. Chce miec pewnosc ze zasob(na razie semafor binarny) zostanie przydzielony watkowi ktory czeka najdluzej.

public class MySemaphore {

int counter;
private LinkedList<Thread> waitingThreads;
private LinkedList<Thread> currentThreads;

public MySemaphore(int n){
	counter = n;
	waitingThreads = new LinkedList<Thread>();
	currentThreads = new LinkedList<Thread>();
}

public void acquire() throws InterruptedException{
	synchronized(this){
		waitingThreads.addLast(Thread.currentThread());
		while (counter==0 || !waitingThreads.peek().equals(Thread.currentThread())){
			this.notifyAll();

// ta linijka powyzej nie daje mi spokoju. Co myslicie o czyms takim? (notiify i zaraz potem wait)

			this.wait();
		}
		counter--;
		Thread t = waitingThreads.pollFirst();
		currentThreads.add(t);
	
	}
	
}

public void release(){
	synchronized(this){
		if(currentThreads.remove(Thread.currentThread())){
			//zeby zwolnic semafor trzeba go miec
			counter++;
		}else{
			waitingThreads.remove(Thread.currentThread());
		}
		this.notifyAll();
	}
}

}

Moje rozwiazanie opiera sie na 2 kolejkach - jedna zawiera watki ktore pracuja na zosobie, druga kolejke oczekujacych. w Petli while (counter==0 || !waitingThreads.peek().equals(Thread.currentThread())) musze wybudzic wszystkich oczekujacych na zasob zeby miec pewnosc ze wybudze 1 w kolejce watek (w waitingThreads). Czy ma ktoś moze inny pomysl, jak zapewnic by watki po kolei dostawaly zasob, a jednoczesnie zeby pilnowac czy ktos nie chce oddac praw do zasobu nie posiadajac ich?

0

Użyj standardowej klasy semaforu.
Jednego dla konsumentów i drugiego dla producentów.

Jeżeli chcesz mieć pewność, że procesy zostaną dopuszczone według FIFO, to ustaw w konstrukorze "fair" na true.

http://java.sun.com/javase/6/docs/api/java/util/concurrent/Semaphore.html#Semaphore%28int,%20boolean%29

Semaphore dlaKonsumentow = new Semaphore(0, true);
Semaphore dlaProducentow = new Semaphore(WIELKOSC_BUFORA, true);

Konsument musi w pętli robić tak:
dlaKonsumentow.acquire()
//pobranie zasobu
dlaProducentow.release()
//konsumpcja

Producent:
//produkcja
dlaProducentow.acquire()
//wstawienie zasobu
dlaKonsumentow.release()

Oczywiście operacje pobrania i wstawienia elementów muszą być w sekcji krytycznej, np. aby dwóch producentów nie wstawiało elementu jednocześnie.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.