2.1 threading
modulu
Python-da çoxaxınlılıq (multithreading) — bu, birdən çox axınların (threads)
eyni zamanda işləməsi üsuludur, bu da prosessor resurslarını daha səmərəli istifadə etməyə imkan verir, xüsusilə də daxil etmə-çıxarma əməliyyatları və ya paralel yerinə yetirilə bilən digər əməliyyatlar üçün.
Python-da çoxaxınlılığın əsas anlayışları:
Axın — bu, bir prosesdəki digər axınlarla paralel işləyə bilən ən kiçik icra vahididir. Eyni prosesdəki bütün axınlar ümumi yaddaşı bölüşdürür, bu da axınlar arasında məlumat mübadiləsinə imkan verir.
Proses — bu, əməliyyat sistemində öz ünvan sahəsi və resursları olan bir proqram nümunəsidir. Axınlardan fərqli olaraq, proseslər bir-birindən təcrid olunmuşdur və məlumatları proseslərarası qarşılıqlı əlaqə (IPC)
vasitəsilə mübadilə edirlər.
GIL
— bu, Python interpreterində bir mexanizmdir ki, bir neçə Python axınının eyni zamanda işləməsinə mane olur. GIL
Python kodunun təhlükəsiz icrasını təmin edir, lakin çoxaxınlı proqramların çoxnüvəli prosessorlarda performansını məhdudlaşdırır.
Vacibdir! Qeyd edin ki, Global Interpreter Lock (GIL) səbəbindən Python-da çoxaxınlılıq, hesablamada intensiv tapşırıqlar üçün performansın əhəmiyyətli dərəcədə artırılmasını təmin etməyə bilər, çünki GIL çoxnüvəli prosessorlarda bir neçə Python axınının eyni anda işləməsinə mane olur.
threading
modulu
threading
modulu Python-da axınlarla işləmək üçün yüksək səviyyəli interfeys təqdim edir. O, axınların yaradılması və idarə edilməsi, onların sinxronlaşdırılması və aralarındakı qarşılıqlı əlaqənin təşkilinə imkan verir. Gəlin bu modulun əsas komponentlərini və funksiyalarını daha ətraflı nəzərdən keçirək.
threading
modulunun əsas komponentləri
Axınlarla işləmək üçün varlıqlar:
-
Thread
— axınların yaradılması və idarə edilməsi üçün əsas sinif. -
Timer
— təyin olunmuş zaman keçdikdən sonra bir funksiyanı icra edən taymer. -
ThreadLocal
— axına məxsus lokal məlumatlar yaratmağa imkan verir.
Axınların sinxronlaşdırma mexanizmi:
-
Lock
— ümumi resurslara eyni zamanda girişin qarşısını almaq üçün sinxronizasiya primitividir. -
Condition
— daha mürəkkəb axın sinxronizasiyası üçün şərti dəyişən. Event
— axınlararası bildiriş üçün primitiv.-
Semaphore
— müəyyən bir bölməni eyni anda işləyə biləcək axınların sayını məhdudlaşdıran primitiv. -
Barrier
— təyin olunmuş sayda axını sinxronlaşdırır, hamısı bariyerə çatana qədər onları bloklayır.
Aşağıda axınlarla işləmək üçün 3 sinif haqqında danışacağam, axınların sinxronlaşdırma mexanizmi isə yaxın zamanda sizə lazım olmayacaq.
2.2 Thread
sinfi
Thread
sinfi — stream-lərin yaradılması və idarə olunması üçün əsas sinifdir. Onun 4 əsas metodu var:
start()
: Stream-ın icrasına başlayır.-
join()
: Cari stream dayandırılır və startedilmiş stream-ın tamamlanmasını gözləyir. is_alive()
: Stream işləyirsə,True
qaytarır.-
run()
: Stream-də icra olunacaq kodu saxlayan metoddur.Thread
sinfindən irs alınarkən override edilir.
Hər şey daha asandır, nəinki görünür — Thread
sinfinin istifadəsinə bir nümunə.
Sadə bir stream-ın icrası
import threading
def worker():
print("Worker thread işləyir")
# Yeni bir stream-in yaradılması
t = threading.Thread(target=worker) # Yeni bir stream obyekti yaratdıq
t.start() # Stream-i başladıq
t.join() # Stream-in tamamlanmasını gözləyirik
print("Əsas stream bitdi")
start
metodu çağırıldıqdan sonra, worker
funksiyası icrasına başlayacaq. Yəni, onun stream-i aktiv stream-lər siyahısına əlavə ediləcək.
Argumentlərin istifadəsi
import threading
def worker(number, text):
print(f"Worker {number}: {text}")
# Argumentlərlə yeni stream yaradılması
t = threading.Thread(target=worker, args=(1, "Salam"))
t.start()
t.join()
Yeni bir stream-ə parametrləri ötürmək üçün sadəcə onları tuple şəklində qeyd edib args
parametrinə təyin etmək lazımdır. target
-də göstərilmiş funksiyanı çağırarkən parametrlər avtomatik olaraq ötürüləcək.
run
metodunun override edilməsi
import threading
class MyThread(threading.Thread):
def run(self):
print("Custom thread işləyir")
# Stream-i yaratmaq və icraya başlamaq
t = MyThread()
t.start()
t.join()
Yeni bir stream-in icrasına başlayacaq funksiyanı göstərmək üçün iki yol var — onu Thread
obyektinin yaradılmasında target
parametri vasitəsilə ötürmək və ya Thread
sinfindən irs alaraq run
funksiyasını override etmək. Hər iki üsul qanuni və geniş istifadə olunur.
2.3 Timer
sinfi
threading
modulundakı Timer
sinfi müəyyən edilmiş vaxt intervalları sonra funksiya işə salır. Bu sinif çoxdilli mühitdə vaxtında yerinə yetirilməli tapşırıqlar üçün əladır.
Timer funksiya və gecikmə vaxtı (saniyə ilə) vasitəsi ilə yaradılır və işə salınır.
-
start()
metodu timer-i işə salır və müəyyən edilmiş vaxt intervalından sonra verilmiş funksiyanı çağırır. -
cancel()
metodu timer-i dayandırmağa icazə verir, əgər hələ işə düşməyibsə. Bu, timer artıq lazım deyilsə, funksiyanın çağırılmamasında faydalıdır.
İstifadə nümunələri:
Gecikmə ilə funksiyanın işə salınması
Bu misalda hello
funksiyası timer işə düşdükdən 5 saniyə sonra çağırılacaq.
import threading
def hello():
print("Salam, dünya!")
# 5 saniyə sonra hello funksiyasını çağıracaq timer yaradılması
t = threading.Timer(5.0, hello)
t.start() # Timer işə salınır
Timer-in işə düşməzdən əvvəl dayandırılması
Burada timer hello
funksiyası işə salınmazdan əvvəl dayandırılır və buna görə heç nə çap olunmayacaq.
import threading
def hello():
print("Salam, dünya!")
# Timer yaradılması
t = threading.Timer(5.0, hello)
t.start() # Timer işə salınır
# Timer-in dayandırılması
t.cancel()
Argumentlərlə bir timer
Bu misalda timer 3 saniyə sonra greet
funksiyasını çağıracaq və ona "Alice"
argumentini ötürəcək.
import threading
def greet(name):
print(f"Salam, {name}!")
# Argumentlərlə timer yaradılması
t = threading.Timer(3.0, greet, args=["Alice"])
t.start()
Timer
sinfi müəyyən bir vaxt sonra tapşırıqların planlaşdırılması üçün əlverişlidir. Bununla belə, timer-lər tam vaxtında icra zəmanəti vermir, çünki bu sistemin yüklənməsi və thread scheduler-in işindən asılıdır.
2.4 ThreadLocal
sinfi
ThreadLocal
sinfi, öz şəxsi lokal məlumatları olan thread-lərin yaradılması üçün nəzərdə tutulub. Bu, çoxthread-li tətbiqlərdə, hər bir thread-in məlumatlarının öz versiyasına malik olması lazım olduqda, konfliktlərdən və sinxronizasiya problemlərindən qaçmaq üçün faydalıdır.
ThreadLocal
-dan istifadə edən hər bir thread öz müstəqil məlumat nüsxəsinə sahib olacaq. ThreadLocal
obyektində saxlanılan məlumatlar hər bir thread üçün unikaldır və digər thread-lərlə paylaşılmır. Bu, yalnız bir thread-in kontekstində istifadə olunan məlumatların saxlanması üçün əlverişlidir, məsələn, veb-tətbiqdə cari istifadəçi və ya məlumat bazası ilə cari əlaqə kimi.
İstifadə nümunələri:
Əsas istifadə
Bu nümunədə, hər bir thread lokal dəyişən value
-yə öz adını təyin edir və onu çıxış edir. value
dəyişənin dəyəri hər bir thread üçün unikaldır.
import threading
# ThreadLocal obyektinin yaradılması
local_data = threading.local()
def process_data():
# Thread-in lokal dəyişəninə dəyər təyin edilir
local_data.value = threading.current_thread().name
# Thread-in lokal dəyişəninə giriş
print(f'Value in {threading.current_thread().name}: {local_data.value}')
threads = []
for i in range(5):
t = threading.Thread(target=process_data)
threads.append(t)
t.start()
for t in threads:
t.join()
İstifadəçinin məlumatlarının veb-tətbiqdə saxlanması
Bu nümunədə, hər bir thread öz istifadəçisinin sorğusunu emal edir. user_data.user
dəyəri hər bir thread üçün unikaldır.
import threading
# ThreadLocal obyektinin yaradılması
user_data = threading.local()
def process_request(user):
# Thread-in lokal dəyişəninə dəyər təyin edilir
user_data.user = user
handle_request()
def handle_request():
# Thread-in lokal dəyişəninə giriş
print(f'Handling request for user: {user_data.user}')
threads = []
users = ['Alice', 'Bob', 'Charlie']
for user in users:
t = threading.Thread(target=process_request, args=(user,))
threads.append(t)
t.start()
for t in threads:
t.join()
Bu, threading
kitabxanasının ən əlverişli 3 sinfi idi. Çox güman ki, işinizdə onları istifadə edəcəksiniz, amma digər siniflərdən ehtimal ki, istifadə etməyəcəksiniz. İndi hamı asinxron funksiyalara və asyncio
kitabxanasına keçir. Bu barədə yaxın vaxtlarda söhbət edəcəyik.
GO TO FULL VERSION