İş parçaları arasındaki etkileşim nasıl senkronize edilir?
AI'dan gelen yanıt
sobes.tech yapay zeka
C/C++ dilinde çoklu iş parçacığı etkileşimi ve senkronizasyonu için birkaç temel mekanizma vardır:
-
Mutexler (Karşılıklı Dışlama): Paylaşılan bir kaynağa özel erişim sağlarlar. Mutex'i alan iş parçacığı, serbest bırakana kadar diğerlerini engeller.
#include <mutex> std::mutex my_mutex; void my_thread_function() { my_mutex.lock(); // Mutex'i al // Paylaşılan kaynak üzerinde çalışma my_mutex.unlock(); // Mutex'i serbest bırak }Veya RAII kullanarak:
#include <mutex> #include <lock_guard> std::mutex my_mutex; void my_thread_function() { std::lock_guard<std::mutex> lock(my_mutex); // Nesne oluşturulduğunda mutex alınır // Paylaşılan kaynak üzerinde çalışma // Scope dışına çıkıldığında mutex otomatik olarak serbest bırakılır } -
Semaforlar: Mutexlerin genelleştirilmiş hali. Bir sayacı tutarlar ve belirli sayıda iş parçacığının aynı anda kaynağa erişmesine izin verirler.
#include <semaphore.h> // POSIX semaforlar için #include <windows.h> // Windows semaforları için sem_t my_semaphore; // POSIX semaforu void my_thread_function() { sem_wait(&my_semaphore); // Semafor sayacını azalt, 0 ise blokla // Kaynak ile çalışma sem_post(&my_semaphore); // Semafor sayacını artır }(Not: Standart C++ doğrudan semafor içermemektedir, ancak sistem kütüphaneleri veya üçüncü taraf uygulamaları aracılığıyla erişilebilirler.)
-
Koşul Değişkenleri: Belirli bir koşulun gerçekleşmesini beklemek için kullanılırlar ve bu sırada mutex serbest bırakılır. Diğer bir iş parçacığı, koşulun yerine getirildiğini bildirebilir.
#include <mutex> #include <condition_variable> std::mutex my_mutex; std::condition_variable my_cv; bool condition_met = false; void waiting_thread() { std::unique_lock<std::mutex> lock(my_mutex); my_cv.wait(lock, []{ return condition_met; }); // Koşul gerçekleşene kadar bekle // Koşul gerçekleşti, kaynak ile çalışma } void notifying_thread() { std::unique_lock<std::mutex> lock(my_mutex); condition_met = true; lock.unlock(); // Bildirimden önce mutex serbest bırakılır (isteğe bağlı, önerilir) my_cv.notify_one(); // Bir iş parçacığını bildir // veya // my_cv.notify_all(); // Tüm bekleyen iş parçacıklarını bildir } -
Atomik İşlemler: Değişkenler üzerinde basit işlemleri (örneğin, artırma, azaltma) tek bir, bölünemez işlem olarak yapmaya olanak tanır, açıkça mutex kilitlemeye gerek kalmadan.
#include <atomic> std::atomic<int> counter(0); void my_thread_function() { counter++; // Atomik artırma // veya: // counter.fetch_add(1); } -
Paylaşılan Mutexler (Shared Mutexes): Birden fazla iş parçacığının aynı anda veri okuyabilmesine izin verir, ancak sadece biri yazabilir.
#include <shared_mutex> // C++17 ve sonrası std::shared_mutex my_shared_mutex; void read_thread() { my_shared_mutex.lock_shared(); // Okuma için kilitle // Veri okuma my_shared_mutex.unlock_shared(); // Okuma için serbest bırak } void write_thread() { my_shared_mutex.lock(); // Yazma için kilitle (özel) // Veri yazma my_shared_mutex.unlock(); // Yazma için serbest bırak } -
Barikatlar (Barriers): Bir grup iş parçacığının, hepsi belirli bir noktaya ulaşana kadar beklemesini sağlar, ardından devam ederler.
#include <barrier> // C++20 std::barrier sync_point(4); // 4 iş parçacığı için bariyer void my_thread_function() { // Barikeden önceki çalışma sync_point.arrive_and_wait(); // Tüm iş parçacıkları bariyere ulaşana kadar bekle // Barikeden sonraki çalışma }
Belirli bir mekanizmanın seçimi, etkileşimin doğası ve paylaşılan kaynaklara bağlıdır.