CodeGym /Kurslar /Python SELF AZ /threading modulu

threading modulu

Python SELF AZ
Səviyyə , Dərs
Mövcuddur

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.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION