কি এবং কেন পুনরাবৃত্তিমূলক মুখ্যকে গ্রহণযোগ্য উত্তরে বর্ণিত এমন জটিল জিনিস হওয়া উচিত নয়।
জালের আশেপাশে কিছু খনন করার পরে আমি আমার বোঝার কথাটি লিখতে চাই।
প্রথমত, আপনার উপলব্ধি করা উচিত যে মুটেেক্স সম্পর্কে কথা বলার সময় , মাল্টি থ্রেড ধারণাগুলি অবশ্যই জড়িত। (মুটেক্স সিঙ্ক্রোনাইজেশনের জন্য ব্যবহৃত হয় my আমার প্রোগ্রামে আমার কেবল 1 টি থ্রেড থাকলে আমার মুটেক্সের প্রয়োজন হবে না)
দ্বিতীয়ত, আপনি একটি সাধারণ মুটেক্স এবং একটি পুনরাবৃত্ত মিউটেক্সের মধ্যে পার্থক্যটি জানতে পারবেন ।
এপিইউ থেকে উদ্ধৃত :
(একটি পুনরাবৃত্তিমূলক মুটেক্স ক) এমন একটি মিউটেক্স টাইপ যা একই থ্রেডটিকে প্রথম আনলক না করে একাধিকবার লক করতে দেয়।
মূল পার্থক্যটি হ'ল একই থ্রেডের মধ্যে , পুনরাবৃত্ত হওয়া লকটি রিলক করা অচলাবস্থার দিকে পরিচালিত করে না, থ্রেডকে অবরুদ্ধ করে না।
এর অর্থ কি এই যে পুনরুক্তিযোগ্য লক কখনও ডেডলক সৃষ্টি করে না?
না, এটি এখনও যদি আনলক না করেই একটি থ্রেডে লক করে রেখে থাকেন এবং এটি অন্য থ্রেডে লক করার চেষ্টা করেন তবে এটি এখনও স্বাভাবিক মুটেক্স হিসাবে অচলাবস্থার কারণ হতে পারে।
আসুন প্রমাণ হিসাবে কিছু কোড দেখুন।
- অচলাবস্থার সাথে স্বাভাবিক মুটেক্স
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t lock;
void * func1(void *arg){
printf("thread1\n");
pthread_mutex_lock(&lock);
printf("thread1 hey hey\n");
}
void * func2(void *arg){
printf("thread2\n");
pthread_mutex_lock(&lock);
printf("thread2 hey hey\n");
}
int main(){
pthread_mutexattr_t lock_attr;
int error;
error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_DEFAULT);
if(error){
perror(NULL);
}
pthread_mutex_init(&lock, &lock_attr);
pthread_t t1, t2;
pthread_create(&t1, NULL, func1, NULL);
pthread_create(&t2, NULL, func2, NULL);
pthread_join(t2, NULL);
}
আউটপুট:
thread1
thread1 hey hey
thread2
সাধারণ অচলাবস্থা উদাহরণ, কোন সমস্যা নেই।
- অচলাবস্থার সাথে পুনরাবৃত্তিমূলক মিটেক্স
শুধু এই লাইনটি uncomment
error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);
এবং অন্য একটি মন্তব্য।
আউটপুট:
thread1
thread1 hey hey
thread2
হ্যাঁ, রিকার্সিভ মিটেক্সও অচলাবস্থার কারণ হতে পারে।
- স্বাভাবিক মুটেক্স, একই থ্রেডে পুনরায় স্থাপন করুন
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
pthread_mutex_t lock;
void func3(){
printf("func3\n");
pthread_mutex_lock(&lock);
printf("func3 hey hey\n");
}
void * func1(void *arg){
printf("thread1\n");
pthread_mutex_lock(&lock);
func3();
printf("thread1 hey hey\n");
}
void * func2(void *arg){
printf("thread2\n");
pthread_mutex_lock(&lock);
printf("thread2 hey hey\n");
}
int main(){
pthread_mutexattr_t lock_attr;
int error;
error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_DEFAULT);
if(error){
perror(NULL);
}
pthread_mutex_init(&lock, &lock_attr);
pthread_t t1, t2;
pthread_create(&t1, NULL, func1, NULL);
sleep(2);
pthread_create(&t2, NULL, func2, NULL);
pthread_join(t2, NULL);
}
আউটপুট:
thread1
func3
thread2
ডেডলক ইন thread t1
, ইন func3
।
(আমি sleep(2)
এটি দেখতে আরও সহজ করার জন্য ব্যবহার করেছি যে অচলাবস্থার কারণে প্রথমদিকে অচলাবস্থার সৃষ্টি হয়েছিল func3
)
- পুনরাবৃত্তিমায়িত মুটেক্স, একই থ্রেডে পুনরায় স্থাপন করুন
আবার, পুনরাবৃত্তিমূলক মিটেক্স লাইনটিকে সংলগ্ন করুন এবং অন্য লাইনে মন্তব্য করুন।
আউটপুট:
thread1
func3
func3 hey hey
thread1 hey hey
thread2
ডেডলক ইন thread t2
, ইন func2
। দেখা? func3
সমাপ্ত এবং প্রস্থান করে, রিলকিং থ্রেডকে বাধা দেয় না বা অচলাবস্থার দিকে পরিচালিত করে না।
সুতরাং, শেষ প্রশ্ন, কেন আমাদের এটি প্রয়োজন?
রিকার্সিভ ফাংশনের জন্য (মাল্টি-থ্রেডেড প্রোগ্রামগুলিতে ডাকা হয় এবং আপনি কিছু সংস্থান / ডেটা সুরক্ষিত করতে চান)।
উদাহরণস্বরূপ আপনার একাধিক থ্রেড প্রোগ্রাম রয়েছে এবং থ্রেড এ তে একটি পুনরাবৃত্ত ফাংশন কল করুন আপনার কাছে এমন কিছু ডেটা রয়েছে যা আপনি সেই পুনরাবৃত্ত ফাংশনে সুরক্ষা রাখতে চান, তাই আপনি মিটেক্স প্রক্রিয়াটি ব্যবহার করেন। এই ফাংশনটির সম্পাদন থ্রেড এ এর ক্রমযুক্ত, সুতরাং আপনি অবশ্যই পুনরাবৃত্তিতে মুটেক্সকে আবার স্থানান্তরিত করবেন। সাধারণ মিটেক্স ব্যবহারের কারণে ডেডলক হয়। এবং এটি সমাধানের জন্য রিসার্সিভ মিটেক্স উদ্ভাবিত।
গৃহীত উত্তর থেকে একটি উদাহরণ দেখুন
কখন পুনরাবৃত্তিমূলক মুদ্রা ব্যবহার করবেন? ।
উইকিপিডিয়া পুনরাবৃত্তিকারী মুটেক্সকে খুব ভালভাবে ব্যাখ্যা করে। একটি পড়ার জন্য অবশ্যই মূল্যবান। উইকিপিডিয়া: প্রেরণকারী_মুটেক্স