আমি পড়ছি pthread.h
; কন্ডিশন ভেরিয়েবল সম্পর্কিত ফাংশনগুলির (যেমন pthread_cond_wait(3)
) আর্গুমেন্ট হিসাবে একটি মিটেক্স প্রয়োজন। কেন? আমি যতদূর বলতে পারি, আমি যুক্তি হিসাবে কেবল একটি মুটেক্স তৈরি করব ? সেই মুটেক্স কী করার কথা?
আমি পড়ছি pthread.h
; কন্ডিশন ভেরিয়েবল সম্পর্কিত ফাংশনগুলির (যেমন pthread_cond_wait(3)
) আর্গুমেন্ট হিসাবে একটি মিটেক্স প্রয়োজন। কেন? আমি যতদূর বলতে পারি, আমি যুক্তি হিসাবে কেবল একটি মুটেক্স তৈরি করব ? সেই মুটেক্স কী করার কথা?
উত্তর:
শর্তটি পরিবর্তনশীল (বা মূলত) বাস্তবায়িত হবার উপায় এটি।
শর্ত পরিবর্তনশীল নিজেই সুরক্ষিত করতে মিউটেক্স ব্যবহৃত হয় । এজন্য অপেক্ষা করার আগে আপনার এটি লক করা দরকার।
অপেক্ষারত "পরমাণুভাবে" মিটেক্সটিকে আনলক করা হবে, যা অন্যকে শর্ত পরিবর্তনশীল (সংকেতের জন্য) অ্যাক্সেসের অনুমতি দেয়। তারপরে যখন শর্ত পরিবর্তনশীলকে সিগন্যাল করা বা সম্প্রচারিত করা হবে, অপেক্ষার তালিকার এক বা একাধিক থ্রেড জেগে উঠবে এবং সেই থ্রেডটির জন্য আবার মিউটেক্সটি যাদুতে লক হয়ে যাবে।
আপনি সাধারণত কন্ডিশন ভেরিয়েবলগুলি সহ নিম্নলিখিত ক্রিয়াকলাপটি দেখেন, তারা কীভাবে কাজ করে তা চিত্রিত করে। নিম্নলিখিত উদাহরণটি একটি শ্রমিক থ্রেড যা একটি শর্ত ভেরিয়েবলের সিগন্যালের মাধ্যমে কাজ দেওয়া হয়।
thread:
initialise.
lock mutex.
while thread not told to stop working:
wait on condvar using mutex.
if work is available to be done:
do the work.
unlock mutex.
clean up.
exit thread.
এই লুপটির মধ্যে কাজটি সম্পন্ন করা হয় তবে অপেক্ষাটি যখন ফিরে আসে তখন সেখানে কিছু উপলব্ধ থাকে। যখন থ্রেডটি কাজ বন্ধ করতে পতাকাঙ্কিত করা হবে (সাধারণত অন্য থ্রেডটি প্রস্থান শর্তটি নির্ধারণ করে তখন এই থ্রেডটি জাগ্রত করতে শর্ত ভেরিয়েবলটিকে লাথি মেরে) লুপটি প্রস্থান করবে, নিঃশব্দটি আনলক হয়ে যাবে এবং এই থ্রেডটি প্রস্থান করবে।
উপরের কোডটি একটি একক-গ্রাহক মডেল হিসাবে কাজ করা চলাকালীন মুটেক্স লক থাকে। বহু-গ্রাহক পরিবর্তনের জন্য, আপনি উদাহরণ হিসাবে ব্যবহার করতে পারেন :
thread:
initialise.
lock mutex.
while thread not told to stop working:
wait on condvar using mutex.
if work is available to be done:
copy work to thread local storage.
unlock mutex.
do the work.
lock mutex.
unlock mutex.
clean up.
exit thread.
এটি অন্য গ্রাহকরা যখন এটি কাজ করছে তখন কাজ পেতে দেয়।
শর্ত পরিবর্তনশীল আপনাকে কিছু শর্তের ভোটের বোঝা থেকে মুক্তি দেয় পরিবর্তে যখন অন্য কিছু হওয়ার দরকার হয় তখন আপনাকে অন্য থ্রেডটি জানাতে দেয়। আর একটি থ্রেড সেই থ্রেডকে বলতে পারে যে কাজটির জন্য নিম্নলিখিতটি পাওয়া যায়:
lock mutex.
flag work as available.
signal condition variable.
unlock mutex.
প্রায়শই যা ভ্রান্তভাবে স্পিউরিয়াস ওয়েকআপস বলা হয় তার বেশিরভাগ অংশই সাধারণত ছিল কারণ তাদের pthread_cond_wait
কল (সম্প্রচার) এর মধ্যে একাধিক থ্রেড সংকেতযুক্ত ছিল , কেউ মুটেক্সের সাথে ফিরে আসবে, কাজ করবে এবং তারপরে অপেক্ষা করবে।
তারপরে যখন কোনও কাজ করার দরকার নেই তখন দ্বিতীয় সংকেতযুক্ত থ্রেড বেরিয়ে আসতে পারে। কাজেই আপনার একটি অতিরিক্ত পরিবর্তনশীল থাকতে হবে যা ইঙ্গিত করে যে কাজটি করা উচিত (এটি মূলত এখানে কনডভার / মুটেক্স জোড়ের সাথে মিটেক্স-সুরক্ষিত ছিল - তবে এটি পরিবর্তন করার আগে মুদ্রাকে লক করার জন্য অন্যান্য থ্রেডগুলি প্রয়োজন ছিল)।
এটা তোলে ছিল টেকনিক্যালি সম্ভব জন্য একটি থ্রেড অন্য প্রক্রিয়া দ্বারা লাথি হচ্ছে একটি শর্ত অপেক্ষার থেকে ফিরে যাওয়ার (এটি জেনুইন কৃত্রিম ওয়েকআপ হয়) কিন্তু, আমার সব অনেক বছর pthreads উপর কাজ উভয় উন্নয়নে / কোডের পরিষেবা এবং ব্যবহারকারী হিসেবে এর মধ্যে আমি এর মধ্যে একটিও পাই নি। এইচপিটির একটি শালীন বাস্তবায়ন ছিল বলেই সম্ভবত এটি ছিল :-)
যে কোনও ক্ষেত্রে, একই কোড যা ভ্রান্ত কেস পরিচালনা করেছিল তা সঠিকভাবে জেনুইন স্পিউরিয়াস ওয়েকআপগুলিও পরিচালনা করেছিল যেহেতু কার্য-উপলভ্য পতাকাগুলি তাদের জন্য সেট করা হবে না।
do something
ভিতরে কেন while
?
একটি শর্ত পরিবর্তনশীল যথেষ্ট সীমাবদ্ধ যদি আপনি কেবল একটি শর্ত সংকেত করতে পারতেন, সাধারণত আপনাকে সিগন্যাল হওয়া শর্তের সাথে সম্পর্কিত এমন কিছু ডেটা পরিচালনা করতে হবে। সিগন্যালিং / জাগ্রত করা জাতিগত অবস্থার পরিচয় না দিয়ে তা অর্জনের জন্য পারমাণবিকভাবে করতে হবে, বা অতিরিক্ত জটিল হতে হবে
pthreads এছাড়াও আপনি বরং প্রযুক্তিগত কারণের জন্য, একটি দিতে পারেন কৃত্রিম ওয়েকআপ । এর অর্থ আপনার একটি প্রিকিকেট যাচাই করা দরকার, যাতে আপনি নিশ্চিত হয়ে উঠতে পারেন যে কন্ডিশনটি আসলে সংকেতযুক্ত ছিল - এবং এটি একটি উত্সাহী জাগ্রত থেকে পৃথক করে। এটির জন্য অপেক্ষা করার ক্ষেত্রে এ জাতীয় শর্তটি রক্ষা করা দরকার - সুতরাং একটি শর্ত পরিবর্তনশীলকে সেই শর্তটি রক্ষা করে এমন কোনও মিউটেক্সকে লক / আনলক করার সময় পরমাণুভাবে অপেক্ষা / জাগ্রত করার একটি উপায় প্রয়োজন।
একটি সাধারণ উদাহরণ বিবেচনা করুন যেখানে আপনাকে অবহিত করা হয় যে কিছু ডেটা উত্পাদিত হয়েছে। হতে পারে অন্য থ্রেড এমন কিছু ডেটা তৈরি করেছে যা আপনি চান এবং সেই ডেটাতে একটি পয়েন্টার সেট করে।
কল্পনা করুন যে কোনও প্রযোজক থ্রেড একটি 'কিছু_ডেটা' পয়েন্টারের মাধ্যমে অন্য গ্রাহক থ্রেডকে কিছু তথ্য দিচ্ছেন।
while(1) {
pthread_cond_wait(&cond); //imagine cond_wait did not have a mutex
char *data = some_data;
some_data = NULL;
handle(data);
}
আপনি স্বাভাবিকভাবেই প্রচুর দৌড়ের অবস্থা পেয়ে যাবেন, অন্য some_data = new_data
ঘুমের জেগে ওঠার পরে যদি অন্য থ্রেড ঠিকঠাক কাজ করে, তবে আপনি যা করার আগেdata = some_data
.Eg এই কেসটি রক্ষার জন্য আপনি সত্যই আপনার নিজের মিটেক্স তৈরি করতে পারবেন না
while(1) {
pthread_cond_wait(&cond); //imagine cond_wait did not have a mutex
pthread_mutex_lock(&mutex);
char *data = some_data;
some_data = NULL;
pthread_mutex_unlock(&mutex);
handle(data);
}
কাজ করবে না, ঘুম থেকে উঠার এবং মিটেক্সটি ধরার মধ্যে এখনও রেস শর্তের সম্ভাবনা রয়েছে। Pthread_cond_wait এর আগে মিউটেক্স স্থাপন করা আপনাকে সাহায্য করে না, কারণ আপনি এখন অপেক্ষা করার সময় মিটেক্সটি ধরে রাখবেন - অর্থাত্ নির্মাতারা কখনই মুটেক্সটি ধরতে পারবেন না। (দ্রষ্টব্য, এক্ষেত্রে আপনি নিজের সাথে সম্পন্ন প্রযোজককে সিগন্যাল করার জন্য দ্বিতীয় শর্তের পরিবর্তনশীল তৈরি করতে পারেন some_data
- যদিও এটি জটিল হয়ে উঠবে, বিশেষত তাই যদি আপনি অনেক প্রযোজক / গ্রাহক চান))
শর্ত থেকে অপেক্ষার / জাগ্রত হওয়ার সময় আপনার নিঃশব্দে মুটিেক্সকে মুক্তি / দখল করার একটি উপায় প্রয়োজন। অজানা শর্তের পরিবর্তনগুলি এটিই করে এবং আপনি যা করতে চান তা এখানে:
while(1) {
pthread_mutex_lock(&mutex);
while(some_data == NULL) { // predicate to acccount for spurious wakeups,would also
// make it robust if there were several consumers
pthread_cond_wait(&cond,&mutex); //atomically lock/unlock mutex
}
char *data = some_data;
some_data = NULL;
pthread_mutex_unlock(&mutex);
handle(data);
}
(প্রযোজককে স্বাভাবিকভাবে একই সতর্কতা অবলম্বন করা উচিত, সর্বদা একই মুটেক্সের সাহায্যে 'কিছু_ডাটা' রক্ষা করা এবং এটি নিশ্চিত করা যে এটি যদি কিছু_ডাটা বর্তমানে থাকে তবে এটি কোনও_ডাটা ওভাররাইট না করে! = NULL)
while (some_data != NULL)
-ওয়েল লুপটি হওয়া উচিত নয় যাতে এটি কমপক্ষে একবার কন্ডিশন ভেরিয়েবলের জন্য অপেক্ষা করে?
while(some_data != NULL)
হওয়া উচিত while(some_data == NULL)
?
পসিক্স শর্তের পরিবর্তনশীলগুলি রাষ্ট্রহীন। সুতরাং রাষ্ট্র বজায় রাখা আপনার দায়িত্ব। যেহেতু অপেক্ষারত বন্ধ করতে অন্য থ্রেডগুলিকে অপেক্ষার থ্রেড এবং থ্রেড উভয়ই রাজ্যে অ্যাক্সেস করা হবে, তাই এটি অবশ্যই একটি মিটেক্স দ্বারা সুরক্ষিত থাকবে। আপনি যদি মনে করেন যে আপনি একটি মুটেক্স ছাড়াই কন্ডিশন ভেরিয়েবলগুলি ব্যবহার করতে পারেন, তবে আপনি বুঝতে পারেন না যে শর্ত পরিবর্তনশীলগুলি রাষ্ট্রহীন।
কন্ডিশনের ভেরিয়েবলগুলি একটি শর্তের চারপাশে নির্মিত হয়। শর্তগুলির পরিবর্তনশীলগুলির জন্য অপেক্ষা করা থ্রেডগুলি কিছু শর্তের জন্য অপেক্ষা করছে। থ্রেডস যা সংকেত শর্তের পরিবর্তনশীলগুলি সেই অবস্থার পরিবর্তন করে। উদাহরণস্বরূপ, কোনও থ্রেড কিছু ডেটা আসার অপেক্ষায় থাকতে পারে। অন্য কিছু থ্রেড লক্ষ্য করতে পারে যে ডেটা এসেছে। "ডেটা এসেছে" শর্তটি।
শর্তের পরিবর্তনশীল, সরলীকৃত এর ক্লাসিক ব্যবহার এখানে:
while(1)
{
pthread_mutex_lock(&work_mutex);
while (work_queue_empty()) // wait for work
pthread_cond_wait(&work_cv, &work_mutex);
work = get_work_from_queue(); // get work
pthread_mutex_unlock(&work_mutex);
do_work(work); // do that work
}
থ্রেডটি কীভাবে কাজের জন্য অপেক্ষা করছে দেখুন। কাজটি একটি মুটেক্স দ্বারা সুরক্ষিত। অপেক্ষার ফলে মিউটেক্স প্রকাশ হয় যাতে অন্য থ্রেডটি এই থ্রেডটিকে কিছু কাজ দিতে পারে। এটি এখানে কীভাবে সংকেত দেওয়া হবে তা এখানে:
void AssignWork(WorkItem work)
{
pthread_mutex_lock(&work_mutex);
add_work_to_queue(work); // put work item on queue
pthread_cond_signal(&work_cv); // wake worker thread
pthread_mutex_unlock(&work_mutex);
}
লক্ষ করুন যে কাজের সারিটি রক্ষা করতে আপনার মুটেক্সের প্রয়োজন । লক্ষ্য করুন যে কন্ডিশন ভেরিয়েবলের নিজেই ধারণা নেই যে সেখানে কাজ আছে কি না। এটি হ'ল, একটি শর্তের পরিবর্তনশীল অবশ্যই একটি শর্তের সাথে যুক্ত হতে হবে , সেই শর্তটি অবশ্যই আপনার কোড দ্বারা বজায় রাখতে হবে এবং যেহেতু এটি থ্রেডগুলির মধ্যে ভাগ করা আছে তাই এটি অবশ্যই একটি মিউেক্স দ্বারা সুরক্ষিত থাকবে।
সমস্ত কন্ডিশনের ভেরিয়েবল ফাংশনগুলির জন্য একটি মুটেক্সের প্রয়োজন হয় না: কেবল অপেক্ষার ক্রিয়াকলাপগুলি করে। সিগন্যাল এবং সম্প্রচারের ক্রিয়াকলাপগুলির জন্য একটি মিউটেক্সের প্রয়োজন হয় না। একটি শর্ত ভেরিয়েবল স্থায়ীভাবে নির্দিষ্ট মিউটেক্সের সাথে যুক্ত হয় না; বাহ্যিক মিউটেক্স শর্ত পরিবর্তনশীলকে সুরক্ষা দেয় না। যদি শর্তের পরিবর্তনশীলটির অভ্যন্তরীণ অবস্থা থাকে যেমন অপেক্ষা অপেক্ষার থ্রেডের সারি, এটি অবশ্যই শর্ত ভেরিয়েবলের অভ্যন্তরীণ লক দ্বারা সুরক্ষিত থাকতে হবে।
অপারেশন অপারেশনগুলি একটি শর্ত পরিবর্তনশীল এবং একটি মিটেক্সকে একত্রিত করে, কারণ:
এই কারণে ওয়েট অপারেশনটি মিউটেক্স এবং শর্ত উভয়ই যুক্তি হিসাবে গ্রহণ করে: যাতে এটি একটি থ্রেডের পারমাণবিক স্থানান্তরকে মুটেক্সের মালিক থেকে অপেক্ষার দিকে পরিচালিত করতে পারে, যাতে থ্রেডটি হারিয়ে যাওয়া জাগ্রত অবস্থার শিকার না হয় ।
একটি থ্রেড একটি মুটেক্স ছেড়ে দেয় এবং একটি স্টেটলেস সিঙ্ক্রোনাইজেশন অবজেক্টের জন্য অপেক্ষা করে, তবে একটি অ্যাটমিক নয় এমনভাবে একটি সময় উইন্ডো উপস্থিত রয়েছে: যখন থ্রেডটির আর তালা নেই, এবং আছে এখনও অবজেক্টের জন্য অপেক্ষা শুরু না। এই উইন্ডোর সময়, অন্য থ্রেড আসতে পারে, প্রতীক্ষিত শর্তটিকে সত্য করে তুলতে পারে, রাষ্ট্রবিহীন সিঙ্ক্রোনাইজেশনের সংকেত দেয় এবং তারপরে অদৃশ্য হয়ে যায়। রাষ্ট্রবিহীন বস্তু মনে রাখে না যে এটি সংকেত ছিল (এটি রাষ্ট্রবিহীন)। সুতরাং তারপরে মূল থ্রেডটি স্টেটলেস সিঙ্ক্রোনাইজেশন অবজেক্টে ঘুমাতে যায় এবং জাগ্রত হয় না, যদিও এটির শর্তটি ইতিমধ্যে সত্য হয়ে গেছে: হারিয়ে যাওয়া জাগ্রত।
কন্ডিশন ভেরিয়েবল ওয়েট ফাংশনগুলি মুটিেক্সটি ছাড়ার আগে কলিং থ্রেডটি নির্ভরযোগ্যভাবে ওয়েকআপটি ধরার জন্য নিবন্ধিত হয়েছে কিনা তা নিশ্চিত করে হারানো জাগাটি এড়াতে পারে। শর্ত পরিবর্তনশীল ওয়েট ফাংশনটি মিউটেক্সটিকে আর্গুমেন্ট হিসাবে গ্রহণ না করলে এটি অসম্ভব।
pthread_cond_broadcast
এবং pthread_cond_signal
ক্রিয়াকলাপগুলি (যে এই প্রশ্নটি সম্পর্কে প্রশ্ন রয়েছে) এমনকি মুটেক্সকে আর্গুমেন্ট হিসাবে গ্রহণ করে না; শুধুমাত্র শর্ত পসিক্স স্পেকটি এখানে রয়েছে । তারা জেগে ওঠার অপেক্ষায় থাকা থ্রেডগুলিতে কী ঘটে যায় কেবল সেই রেফারেন্সে মিউটেক্সটি উল্লেখ করা হয়।
অন্যান্য উত্তরগুলি এই পৃষ্ঠার মতো সংক্ষিপ্ত এবং পাঠযোগ্য হিসাবে খুঁজে পাচ্ছি না । সাধারণত ওয়েটিং কোডটি এরকম কিছু দেখায়:
mutex.lock()
while(!check())
condition.wait()
mutex.unlock()
wait()
নিঃশব্দে মোড়ানোর জন্য তিনটি কারণ রয়েছে :
signal()
আগে উঠতে পারে wait()
এবং আমরা এই জাগ্রত অনুভব করতে চাই।check()
অন্য থ্রেড থেকে পরিবর্তনের উপর নির্ভরশীল, সুতরাং যাইহোক এটির ক্ষেত্রে আপনার পারস্পরিক বর্জন প্রয়োজন।তৃতীয় বিষয়টি সর্বদা উদ্বেগের বিষয় নয় - historicalতিহাসিক প্রসঙ্গটি নিবন্ধ থেকে এই কথোপকথনের সাথে লিঙ্কযুক্ত ।
উদ্দীপনা জাগ্রত করার বিষয়টি প্রায়শই এই প্রক্রিয়াটির সাথে উল্লেখ করা হয় (অর্থাত্ অপেক্ষার থ্রেডটি signal()
না ডেকে জেগে থাকে )। যাইহোক, এই জাতীয় ইভেন্টগুলি লুপেড দ্বারা পরিচালিত হয় check()
।
কন্ডিশনের ভেরিয়েবলগুলি একটি মুটেক্সের সাথে যুক্ত কারণ এটি এড়াতে পারে এমন একমাত্র উপায় যা এড়ানোর জন্য ডিজাইন করা হয়েছে।
// incorrect usage:
// thread 1:
while (notDone) {
pthread_mutex_lock(&mutex);
bool ready = protectedReadyToRunVariable
pthread_mutex_unlock(&mutex);
if (ready) {
doWork();
} else {
pthread_cond_wait(&cond1); // invalid syntax: this SHOULD have a mutex
}
}
// signalling thread
// thread 2:
prepareToRunThread1();
pthread_mutex_lock(&mutex);
protectedReadyToRuNVariable = true;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond1);
Now, lets look at a particularly nasty interleaving of these operations
pthread_mutex_lock(&mutex);
bool ready = protectedReadyToRunVariable;
pthread_mutex_unlock(&mutex);
pthread_mutex_lock(&mutex);
protectedReadyToRuNVariable = true;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond1);
if (ready) {
pthread_cond_wait(&cond1); // uh o!
এই মুহুর্তে, এমন কোনও থ্রেড নেই যা শর্ত পরিবর্তনশীলকে সিগন্যাল করতে চলেছে, সুতরাং থ্রেড 1 চিরতরে অপেক্ষা করবে, যদিও সুরক্ষিত রেডিটোরুনে ভেরিয়েবল বলে যে এটি যেতে প্রস্তুত!
এর চারপাশের একমাত্র উপায় শর্ত ভেরিয়েবলগুলি পরমাণুভাবে মুটেক্সকে ছেড়ে দেওয়ার সময় একই সাথে শর্ত ভেরিয়েবলের জন্য অপেক্ষা করা শুরু করে। এই কারণেই কনড_উইট ফাংশনটির জন্য একটি মিটেক্স প্রয়োজন
// correct usage:
// thread 1:
while (notDone) {
pthread_mutex_lock(&mutex);
bool ready = protectedReadyToRunVariable
if (ready) {
pthread_mutex_unlock(&mutex);
doWork();
} else {
pthread_cond_wait(&mutex, &cond1);
}
}
// signalling thread
// thread 2:
prepareToRunThread1();
pthread_mutex_lock(&mutex);
protectedReadyToRuNVariable = true;
pthread_cond_signal(&mutex, &cond1);
pthread_mutex_unlock(&mutex);
আপনি কল করার সময় মুটেক্সটি লক হওয়ার কথা pthread_cond_wait
; আপনি যখন এটিকে ডাকছেন তখন উভয়ই শ্বেতকে তালাবদ্ধ করে এবং শর্তটি বন্ধ করে দেয়। শর্তটি সংকেত দেওয়া হয়ে গেলে এটি পরমাণুভাবে আবার এটি লক করে ফিরে আসে।
এটি যদি ইচ্ছা হয় তবে পূর্বাভাসযোগ্য সময়সূচী বাস্তবায়নের অনুমতি দেয়, যে থ্রেডটি যে সিগন্যালিং করে তা মুটেক্সটি প্রক্রিয়াজাতকরণের জন্য অপেক্ষা করতে পারে এবং তারপরে শর্তটি সংকেত দেয়।
আপনি যদি শর্ত পরিবর্তনের প্রকৃত উদাহরণ চান তবে আমি ক্লাসে একটি অনুশীলন করেছি:
#include "stdio.h"
#include "stdlib.h"
#include "pthread.h"
#include "unistd.h"
int compteur = 0;
pthread_cond_t varCond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex_compteur;
void attenteSeuil(arg)
{
pthread_mutex_lock(&mutex_compteur);
while(compteur < 10)
{
printf("Compteur : %d<10 so i am waiting...\n", compteur);
pthread_cond_wait(&varCond, &mutex_compteur);
}
printf("I waited nicely and now the compteur = %d\n", compteur);
pthread_mutex_unlock(&mutex_compteur);
pthread_exit(NULL);
}
void incrementCompteur(arg)
{
while(1)
{
pthread_mutex_lock(&mutex_compteur);
if(compteur == 10)
{
printf("Compteur = 10\n");
pthread_cond_signal(&varCond);
pthread_mutex_unlock(&mutex_compteur);
pthread_exit(NULL);
}
else
{
printf("Compteur ++\n");
compteur++;
}
pthread_mutex_unlock(&mutex_compteur);
}
}
int main(int argc, char const *argv[])
{
int i;
pthread_t threads[2];
pthread_mutex_init(&mutex_compteur, NULL);
pthread_create(&threads[0], NULL, incrementCompteur, NULL);
pthread_create(&threads[1], NULL, attenteSeuil, NULL);
pthread_exit(NULL);
}
এটি ধারণাগত প্রয়োজনের চেয়ে একটি নির্দিষ্ট নকশার সিদ্ধান্ত হিসাবে প্রতীয়মান।
প্রতি পাইথ্রেডস ডকস অনুসারে মিউটেক্সটি আলাদা না হওয়ার কারণ হ'ল তাদের একত্রিত করার মাধ্যমে একটি উল্লেখযোগ্য পারফরম্যান্স উন্নতি হয়েছে এবং তারা আশা করেন যে সাধারণ জাতি অবস্থার কারণে আপনি যদি কোনও মিটেক্স ব্যবহার না করেন তবে এটি প্রায় সর্বদা যাইহোক সম্পন্ন হবে।
https://linux.die.net/man/3/pthread_cond_wait
শব্দের বৈশিষ্ট্য এবং শর্ত ভেরিয়েবলগুলি
পরামর্শ দেওয়া হয়েছিল যে শর্ত অপেক্ষা থেকে মুটেক্স অধিগ্রহণ এবং রিলিজ হ্রাস পাবে। এটি প্রত্যাখ্যান করা হয়েছিল কারণ এটি অপারেশনের সম্মিলিত প্রকৃতি যা বাস্তবে রিয়েলটাইম বাস্তবায়ন সহজতর করে। এই বাস্তবায়নগুলি কমনীয়ভাবে শর্ত পরিবর্তনশীল এবং মিউটেক্সের মধ্যে এমনভাবে একটি উচ্চ-অগ্রাধিকারের থ্রেডকে কল করতে পারে যা কলারের কাছে স্বচ্ছ। এটি অতিরিক্ত প্রসঙ্গের স্যুইচগুলি প্রতিরোধ করতে পারে এবং অপেক্ষার থ্রেডটি সিগন্যাল করা হলে একটি মিটেক্সের আরও নির্ধারিত অধিগ্রহণ সরবরাহ করতে পারে। সুতরাং, সুষ্ঠুতা এবং অগ্রাধিকার সংক্রান্ত সমস্যাগুলি সিডিয়ুলিং শৃঙ্খলা দ্বারা সরাসরি মোকাবিলা করা যেতে পারে। তদতিরিক্ত, বর্তমান শর্ত অপেক্ষা অপারেশন বিদ্যমান অনুশীলনের সাথে মেলে।
সে সম্পর্কে একাধিক ছাড় রয়েছে, তবুও আমি নিম্নলিখিত উদাহরণ দিয়ে এটিকে প্রকাশ করতে চাই।
1 void thr_child() {
2 done = 1;
3 pthread_cond_signal(&c);
4 }
5 void thr_parent() {
6 if (done == 0)
7 pthread_cond_wait(&c);
8 }
কোড স্নিপেটে কী সমস্যা? সামনের দিকে যাওয়ার আগে কিছুটা ভাবুন।
বিষয়টি সত্যই সূক্ষ্ম। যদি পিতামাতারা অনুরোধ করে
thr_parent()
এবং তার মানটি পরীক্ষা করে done
তবে তা দেখতে পাবে 0
এবং এভাবে ঘুমাতে যাওয়ার চেষ্টা করবে। তবে ঘুমানোর জন্য অপেক্ষা করার ডাক দেওয়ার ঠিক আগে, বাবা-মা 6-7-র লাইনের মধ্যে বাধা পান এবং বাচ্চা ছুটে যায়। শিশু রাষ্ট্র পরিবর্তনশীল পরিবর্তন
done
করতে 1
এবং সংকেত, কিন্তু কোন থ্রেড অপেক্ষা করছে এবং এইভাবে কোন থ্রেড woken করা হয়। যখন পিতামাতারা আবার দৌড়ান, তখন এটি চিরকাল ঘুমায়, যা সত্যই অত্যন্ত উদ্বেগজনক।
যদি আলাদাভাবে লকগুলি অর্জন করার সময় সেগুলি সম্পাদন করা হয় তবে কী হবে?