Condition Variables হল একটি সমান্তরাল প্রোগ্রামিং কৌশল যা থ্রেডের মধ্যে সিঙ্ক্রোনাইজেশন করার জন্য ব্যবহৃত হয়। এটি বিশেষভাবে উপকারী যখন একটি থ্রেড অপেক্ষা করে যে একটি শর্ত পূর্ণ হবে, যেমন ডেটার প্রস্তুতি, সম্পদ উপলব্ধতা, বা কোনও ইভেন্টের ঘটনা।
Condition Variables এর কার্যকারিতা
Condition variables সাধারণত mutexes এর সাথে ব্যবহার করা হয়। একটি থ্রেড একটি condition variable-এ "wait" করতে পারে, এবং অন্য একটি থ্রেড condition variable-এ "signal" বা "broadcast" করতে পারে, যখন এটি শর্তটি পূরণ করে।
Condition Variables ব্যবহারের ধাপ
১. Mutex তৈরি করা: প্রথমে একটি mutex তৈরি করতে হয়, যা condition variable এর সাথে সম্পর্কিত হবে।
২. Condition Variable তৈরি করা: একটি condition variable তৈরি করা হয়।
৩. Wait করা: যখন একটি থ্রেড একটি নির্দিষ্ট শর্তের জন্য অপেক্ষা করে, এটি mutex লক করে এবং condition variable-এ wait করে।
৪. Signal/Broadcast করা: যখন অন্য একটি থ্রেড শর্ত পূরণ করে, তখন এটি condition variable-এ signal বা broadcast করে।
৫. Mutex আনলক করা: wait করার পর, mutex আনলক করতে হয়।
উদাহরণ
নিচে একটি সাধারণ উদাহরণ দেওয়া হলো যেখানে একটি producer-consumer সমস্যা সমাধান করা হয়েছে।
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define BUFFER_SIZE 5
int buffer[BUFFER_SIZE]; // শেয়ার্ড বাফার
int count = 0; // বাফারের বর্তমান সংখ্যা
pthread_mutex_t mutex; // মিউটেক্স
pthread_cond_t cond_full; // বাফার পূর্ণ হলে সংকেত
pthread_cond_t cond_empty; // বাফার খালি হলে সংকেত
void* producer(void* arg) {
for (int i = 0; i < 10; i++) {
pthread_mutex_lock(&mutex); // মিউটেক্স লক করা
while (count == BUFFER_SIZE) { // যদি বাফার পূর্ণ হয়
pthread_cond_wait(&cond_full, &mutex); // অপেক্ষা করা
}
buffer[count] = i; // নতুন আইটেম যোগ করা
printf("Produced: %d\n", i);
count++; // সংখ্যা বাড়ানো
pthread_cond_signal(&cond_empty); // খালি সংকেত পাঠানো
pthread_mutex_unlock(&mutex); // মিউটেক্স আনলক করা
}
return NULL;
}
void* consumer(void* arg) {
for (int i = 0; i < 10; i++) {
pthread_mutex_lock(&mutex); // মিউটেক্স লক করা
while (count == 0) { // যদি বাফার খালি হয়
pthread_cond_wait(&cond_empty, &mutex); // অপেক্ষা করা
}
int item = buffer[count - 1]; // আইটেম নেওয়া
printf("Consumed: %d\n", item);
count--; // সংখ্যা কমানো
pthread_cond_signal(&cond_full); // পূর্ণ সংকেত পাঠানো
pthread_mutex_unlock(&mutex); // মিউটেক্স আনলক করা
}
return NULL;
}
int main() {
pthread_t prod_thread, cons_thread;
pthread_mutex_init(&mutex, NULL); // মিউটেক্স শুরু করা
pthread_cond_init(&cond_full, NULL); // পূর্ণ সংকেত শুরু করা
pthread_cond_init(&cond_empty, NULL); // খালি সংকেত শুরু করা
pthread_create(&prod_thread, NULL, producer, NULL); // উৎপাদক থ্রেড তৈরি করা
pthread_create(&cons_thread, NULL, consumer, NULL); // ভোক্তা থ্রেড তৈরি করা
pthread_join(prod_thread, NULL); // উৎপাদক থ্রেডের সমাপ্তি অপেক্ষা করা
pthread_join(cons_thread, NULL); // ভোক্তা থ্রেডের সমাপ্তি অপেক্ষা করা
pthread_mutex_destroy(&mutex); // মিউটেক্স ধ্বংস করা
pthread_cond_destroy(&cond_full); // পূর্ণ সংকেত ধ্বংস করা
pthread_cond_destroy(&cond_empty); // খালি সংকেত ধ্বংস করা
return 0;
}
উদাহরণ বিশ্লেষণ
১. শেয়ার্ড বাফার: এখানে একটি বাফার তৈরি করা হয়েছে, যেখানে উৎপাদক এবং ভোক্তা ডেটা বিনিময় করে।
২. মিউটেক্স: pthread_mutex_t mutex ব্যবহার করে শেয়ার্ড ডেটার সুরক্ষা নিশ্চিত করা হয়।
৩. Condition Variables: cond_full এবং cond_empty ব্যবহৃত হয়েছে, যা উৎপাদক এবং ভোক্তার মধ্যে সিঙ্ক্রোনাইজেশন নিশ্চিত করে।
৪. Wait এবং Signal: উৎপাদক যখন বাফার পূর্ণ থাকে তখন অপেক্ষা করে, এবং ভোক্তা যখন বাফার খালি থাকে তখন অপেক্ষা করে। সিগন্যাল পাঠিয়ে তারা একে অপরকে জানায় যে তারা ডেটা পাঠাতে বা গ্রহণ করতে প্রস্তুত।
উপসংহার
Condition Variables হল একটি শক্তিশালী সিঙ্ক্রোনাইজেশন কৌশল যা থ্রেডগুলির মধ্যে অভিগম্যতা নিয়ন্ত্রণ করতে ব্যবহৃত হয়। সঠিকভাবে ব্যবহার করলে এটি প্রোগ্রামিংয়ে সমান্তরাল কার্যক্রমের নিরাপত্তা এবং কার্যকারিতা নিশ্চিত করতে সহায়ক। Condition variables বিশেষ করে উৎপাদক-ভোক্তা সমস্যা এবং অন্যান্য জটিল থ্রেডিং সমস্যাগুলিতে ব্যাপকভাবে ব্যবহৃত হয়।