Leader/Follower jest o sprawnie do czynienia z wieloma pracownikami. Kiedy nie masz pracy (zadań), co robią twoi pracownicy lub pracownicy? Powszechne, proste podejście polega na tym, że pojedynczy wątek konsumenta wysyła zadania do pracowników, albo poprzez utworzenie wątku, albo użycie puli wątków. Omawiany wzorzec zapewnia alternatywne podejście, które pozwala uniknąć synchronizacji między dyspozytorem a pracownikiem, dzięki temu, że wątek (wiodący), który dostaje zadanie, wykonuje zadanie robocze. Promuje pracownika oczekującego na pozycję lidera, aby system był responsywny.
Należy pamiętać, że ten artykuł omawia mechanizmy niższego poziomu oczekujące na pracę, które nie obsługują wielu wątków oczekujących w tej samej "kolejce" pracy. Konstrukty wyższego poziomu, takie jak kolejki komunikatów, które obsługują wiele wątków roboczych, wszystkie wykonujące blokowanie czytane na tym samym źródle (konkurujący konsumenci AKA) mogą nie uzyskać opisanych korzyści. Przy wyższym poziomie abstrakcji łatwiej jest programować, ale zazwyczaj kosztem tego rodzaju wydajności, którą można uzyskać dzięki bardziej niskopoziomowemu podejściu.
Edit1:
Oto wymyślona próbki (pseudokod tylko). Pamiętaj, że nie napisałem tego artykułu ani nie przetestowałem go, więc nie mogę naprawdę mówić o wydajności jednego z nich. Miejmy nadzieję, że pokazuje różnicę w stylu.
// in QueueHandler processing loop
while(true)
{
// read, blocking until one arrives
Request req = requestQueue.BlockingRead();
// we have a unit of work now but the QueueHandler should not process it
// because if it is long running then no new requests can be handled.
// so we spawn/dispatch to a thread
ThreadPool.QueueWorkItem(req);
// or new Thread(DoWork(), req).Start;
// at this point we know that the request will get picked up in
// an unknown but hopefully very short amount of time by a
// waiting (sleeping/blocking) or new thread and it will get passed the
// work. But doing so required the use of thread synchronization
// primitives that can cause all processors to flush their caches
// and other expensive stuff.
} // now loop back up to read the next request
VS
// in Leader
while(true)
{
// I'm the leader, blocking read until a request arrives
Request req = queue.BlockingRead();
// We have a unit of work and we are going to process it ourselves.
// But first we notify a follower.
Followers.PromoteOne();
// work on the request in this thread!
DoWorkOn(req);
// now that I'm done, wait to the the leader
Followers.BlockingWaitToBeLeader();
}
, więc różnica polega na tym, że to podejście niskiego poziomu nie blokuje i dlatego jest szybsze do wykonania? – Nicolas
Ma mniej rywalizacji, mniej pracy między wątkami. Koordynowanie komunikacji/synchronizacji wątków często wymaga użycia blokad itp., Które mają bardzo negatywny wpływ na kod działający na wielu procesorach. – tcarvin
ale czy możesz wskazać konkretną różnicę między tym a kolejkami pracy? nadal nie mogę zrozumieć, dlaczego kolejki robocze wymagają większego blokowania. – Nicolas