Sobes.tech
Middle+

Czy pracowałeś z semaforami w swojej praktyce?

sobes.tech AI

Odpowiedź od AI

Tak, musiałem używać semaforów, szczególnie w kontekście pracy z wielowątkowością w aplikacjach Android.

Semafory w Javie (java.util.concurrent.Semaphore) służą do ograniczania liczby wątków, które mogą jednocześnie uzyskać dostęp do określonego zasobu. Jest to przydatne w scenariuszach, gdzie zasób ma ograniczoną "pojemność", na przykład pulę połączeń lub ograniczoną liczbę dostępnych slotów.

Główne metody, z którymi pracowałem, to:

  • acquire(): Blokuje bieżący wątek, aż dostępne będzie pozwolenie.
  • acquire(int permits): Blokuje bieżący wątek, aż dostępna będzie wskazana liczba pozwoleń.
  • release(): Zwraca pozwolenie semaforowi, zwiększając liczbę dostępnych pozwoleń.
  • release(int permits): Zwraca wskazaną liczbę pozwoleń.
  • tryAcquire(): Próbuje uzyskać pozwolenie bez blokowania wątku.
  • availablePermits(): Zwraca obecną liczbę dostępnych pozwoleń.

Przykład użycia:

import java.util.concurrent.Semaphore;

public class ResourcePool {

    private static final int MAX_AVAILABLE = 5;
    private final Semaphore permits = new Semaphore(MAX_AVAILABLE, true); // Semafor sprawiedliwy

    public void useResource() throws InterruptedException {
        permits.acquire(); // Żądanie pozwolenia
        try {
            // Logika korzystania z zasobu (np. praca z pulą połączeń)
            System.out.println(Thread.currentThread().getName() + " korzysta z zasobu.");
            Thread.sleep(1000); // Symulacja pracy z zasobem
        } finally {
            permits.release(); // Zwrot pozwolenia
            System.out.println(Thread.currentThread().getName() + " zakończył korzystanie z zasobu.");
        }
    }

    public static void main(String[] args) {
        ResourcePool pool = new ResourcePool();
        // Tworzymy kilka wątków, które będą próbowały używać zasobu
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    pool.useResource();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

W tym przykładzie semafor permits jest inicjalizowany z 5 pozwoleniami, co oznacza, że jednocześnie tylko 5 wątków może znajdować się w bloku try, korzystając z zasobu. Metoda acquire() blokuje wątki, jeśli wszystkie pozwolenia są zajęte, aż inne wątki wywołają release().

Semafory są przydatne do zarządzania dostępem do ograniczonych pul zasobów, ale należy uważać na potencjalne problemy, takie jak deadlocki, jeśli nie zarządza się poprawnie uzyskiwaniem i zwalnianiem pozwoleń. Użycie try z blokiem finally do wywołania release() jest dobrą praktyką, aby zapewnić zwolnienie zasobów nawet w przypadku wyjątków.