56 lines
1.9 KiB
Python
56 lines
1.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Демо: Semaphore — лимит одновременного доступа к ресурсу.
|
|
|
|
Запуск из корня курса:
|
|
python lab05_sync/examples/02_semaphore_demo.py
|
|
|
|
Имитация: 10 «клиентов», ресурс допускает 3 одновременных подключения.
|
|
Семафор гарантирует: активных клиентов никогда не больше 3.
|
|
"""
|
|
import os
|
|
import sys
|
|
import threading
|
|
import time
|
|
|
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
|
|
|
|
MAX_CONN = 3
|
|
N_CLIENTS = 10
|
|
DELAY = 0.2
|
|
|
|
active = 0
|
|
active_lock = threading.Lock()
|
|
max_seen = [0]
|
|
|
|
|
|
def client(idx, sem):
|
|
global active
|
|
with sem: # ждём свободный «слот»
|
|
with active_lock:
|
|
active += 1
|
|
max_seen[0] = max(max_seen[0], active)
|
|
print(f" клиент {idx:>2} подключился (активно: {active})")
|
|
time.sleep(DELAY) # «работа с ресурсом»
|
|
with active_lock:
|
|
active -= 1
|
|
print(f" клиент {idx:>2} отключился (активно: {active})")
|
|
|
|
|
|
def main():
|
|
sem = threading.Semaphore(MAX_CONN)
|
|
threads = [threading.Thread(target=client, args=(i, sem))
|
|
for i in range(N_CLIENTS)]
|
|
t0 = time.perf_counter()
|
|
for t in threads:
|
|
t.start()
|
|
for t in threads:
|
|
t.join()
|
|
total = time.perf_counter() - t0
|
|
|
|
print(f"\nмаксимум одновременно: {max_seen[0]} (лимит {MAX_CONN})")
|
|
print(f"время: {total:.2f} c, идеал ≈ {N_CLIENTS / MAX_CONN * DELAY:.2f} c")
|
|
print("Если max_seen > лимита — семафор сломан (такого быть не должно).")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |