কেন pthreads 'শর্তের পরিবর্তনশীল ফাংশনগুলির জন্য একটি মুটেক্সের প্রয়োজন?


182

আমি পড়ছি pthread.h; কন্ডিশন ভেরিয়েবল সম্পর্কিত ফাংশনগুলির (যেমন pthread_cond_wait(3)) আর্গুমেন্ট হিসাবে একটি মিটেক্স প্রয়োজন। কেন? আমি যতদূর বলতে পারি, আমি যুক্তি হিসাবে কেবল একটি মুটেক্স তৈরি করব ? সেই মুটেক্স কী করার কথা?

উত্তর:


194

শর্তটি পরিবর্তনশীল (বা মূলত) বাস্তবায়িত হবার উপায় এটি।

শর্ত পরিবর্তনশীল নিজেই সুরক্ষিত করতে মিউটেক্স ব্যবহৃত হয় । এজন্য অপেক্ষা করার আগে আপনার এটি লক করা দরকার।

অপেক্ষারত "পরমাণুভাবে" মিটেক্সটিকে আনলক করা হবে, যা অন্যকে শর্ত পরিবর্তনশীল (সংকেতের জন্য) অ্যাক্সেসের অনুমতি দেয়। তারপরে যখন শর্ত পরিবর্তনশীলকে সিগন্যাল করা বা সম্প্রচারিত করা হবে, অপেক্ষার তালিকার এক বা একাধিক থ্রেড জেগে উঠবে এবং সেই থ্রেডটির জন্য আবার মিউটেক্সটি যাদুতে লক হয়ে যাবে।

আপনি সাধারণত কন্ডিশন ভেরিয়েবলগুলি সহ নিম্নলিখিত ক্রিয়াকলাপটি দেখেন, তারা কীভাবে কাজ করে তা চিত্রিত করে। নিম্নলিখিত উদাহরণটি একটি শ্রমিক থ্রেড যা একটি শর্ত ভেরিয়েবলের সিগন্যালের মাধ্যমে কাজ দেওয়া হয়।

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 উপর কাজ উভয় উন্নয়নে / কোডের পরিষেবা এবং ব্যবহারকারী হিসেবে এর মধ্যে আমি এর মধ্যে একটিও পাই নি। এইচপিটির একটি শালীন বাস্তবায়ন ছিল বলেই সম্ভবত এটি ছিল :-)

যে কোনও ক্ষেত্রে, একই কোড যা ভ্রান্ত কেস পরিচালনা করেছিল তা সঠিকভাবে জেনুইন স্পিউরিয়াস ওয়েকআপগুলিও পরিচালনা করেছিল যেহেতু কার্য-উপলভ্য পতাকাগুলি তাদের জন্য সেট করা হবে না।


3
'কিছু করুন' এমন সময় লুপের ভিতরে থাকা উচিত নয়। আপনি চাইবেন যে আপনার সময়টির লুপটি কেবল শর্তটি পরীক্ষা করতে পারে, অন্যথায় আপনি যদি কিছু উত্সাহী জাগ্রত পান তবে আপনি 'কিছু করতেও' পারেন।
টি

1
না, ত্রুটি পরিচালনা করা এর পরে দ্বিতীয়। অজানা কারণে, আপাত কোনও কারণ ছাড়াই (কোনও উত্সাহী জাগরণ), এবং কোনও ত্রুটি ছাড়াই আপনি জাগ্রত হতে পারেন। আপনি জেগে ওঠার পরে আপনাকে 'কিছু শর্ত' পুনরায় পরীক্ষা করা দরকার।
টি

1
আমি নিশ্চিত নই যে আমি বুঝেছি. আমি একই প্রতিক্রিয়া ছিল টি ; লুপের do somethingভিতরে কেন while?
এলিওটিটিসিবল

1
সম্ভবত আমি এটি যথেষ্ট পরিষ্কার করছি না। লুপটি কাজের প্রস্তুত হওয়ার অপেক্ষা না করে যাতে আপনি এটি করতে পারেন। লুপটি মূল "অসীম" কাজের লুপ। যদি আপনি কনড_ওয়াইট থেকে ফিরে যান এবং কাজের পতাকাটি সেট করা থাকে, আপনি কাজটি করেন তবে আবার লুপ করুন। "যখন কিছু শর্ত" কেবল তখনই মিথ্যা হবে যখন আপনি থ্রেডটি কাজ করা বন্ধ করতে চান যেখানে এটি মুটেক্সকে প্রকাশ করবে এবং সম্ভবত সম্ভবত প্রস্থান করবে।
paxdiablo

7
@ স্টেফানভ "মিউটেক্স এখনও কন্ডিশন ভেরিয়েবলকে রক্ষা করতে পারে, এটিকে রক্ষা করার অন্য কোনও উপায় নেই": মিউটেক্স শর্ত পরিবর্তনশীলকে রক্ষা করার জন্য নয় ; এটি ভবিষ্যদ্বাণীপূর্ণ ডেটা সুরক্ষিত করার জন্য , তবে আমি মনে করি আপনি জেনে গেছেন যে আপনার বক্তব্যটি যে বিবৃতিটি অনুসরণ করেছে তা পড়ে। আপনি শর্তটিকে বৈধভাবে বৈকল্পিকভাবে সিগন্যাল করতে পারেন, এবং প্রয়োগের দ্বারা সম্পূর্ণরূপে সমর্থিত হন, মেটেক্সের পোস্ট- আনলক প্রিডিকেটটি মোড়ানো করে রাখবেন এবং বাস্তবে আপনি কিছু ক্ষেত্রে এটি করার ক্ষেত্রে বিতর্ক থেকে মুক্তি পাবেন ।
WhozCraig

59

একটি শর্ত পরিবর্তনশীল যথেষ্ট সীমাবদ্ধ যদি আপনি কেবল একটি শর্ত সংকেত করতে পারতেন, সাধারণত আপনাকে সিগন্যাল হওয়া শর্তের সাথে সম্পর্কিত এমন কিছু ডেটা পরিচালনা করতে হবে। সিগন্যালিং / জাগ্রত করা জাতিগত অবস্থার পরিচয় না দিয়ে তা অর্জনের জন্য পারমাণবিকভাবে করতে হবে, বা অতিরিক্ত জটিল হতে হবে

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)-ওয়েল লুপটি হওয়া উচিত নয় যাতে এটি কমপক্ষে একবার কন্ডিশন ভেরিয়েবলের জন্য অপেক্ষা করে?
বিচারক মেয়েগার্ডেন

3
না, আপনি যা অপেক্ষা করছেন, তা 'কিছু_ডাটা' -র জন্য নন। যদি এটি "প্রথম বার" শূন্য হয় তবে দুর্দান্ত, আপনি মুটেক্সটি ধরে রেখেছেন এবং নিরাপদে ডেটা ব্যবহার করতে পারেন। আপনার যদি করণীয় / লুপ থাকলে আপনি বিজ্ঞপ্তিটি মিস করবেন যদি কেউ অপেক্ষা করার আগে শর্তটি পরিবর্তনশীল সিগন্যাল করে (এটি
নং

4
আমি কেবল এই প্রশ্নটিতেই হোঁচট খেয়েছি এবং সত্যই, এই উত্তরটি প্যাক্সিডাব্লোর উত্তরের তুলনায় এতটা কম পয়েন্ট রয়েছে যে সঠিক উত্তর রয়েছে (অণুবাদ এখনও প্রয়োজন, মিটেক্স কেবল শর্ত পরিচালনার জন্য প্রয়োজন, হ্যান্ডলিং বা অবহিত করার জন্য নয়)। আমি যে ঠিক কিভাবে Stackoverflow কাজ ...
stefaanv

@ স্টেফানভ, আপনি যদি আমার উত্তরটির মতামত হিসাবে ত্রুটিগুলি বিশদভাবে বর্ণনা করতে চান তবে আমি কয়েক মাস পরে :-) না হয়ে সময় মতো ফ্যাশনে তাদের দেখতে পাচ্ছি: আমি এগুলি সংশোধন করতে পেরে খুশি হব। আপনার সংক্ষিপ্ত বাক্যাংশগুলি আপনি কী বলার চেষ্টা করছেন তা বাস্তবায়িত করার জন্য আমাকে সত্যিই যথেষ্ট বিশদ দেয় না।
প্যাক্সিডিয়াবলো

1
@ কোন, না while(some_data != NULL)হওয়া উচিত while(some_data == NULL)?
এরিক জেড

30

পসিক্স শর্তের পরিবর্তনশীলগুলি রাষ্ট্রহীন। সুতরাং রাষ্ট্র বজায় রাখা আপনার দায়িত্ব। যেহেতু অপেক্ষারত বন্ধ করতে অন্য থ্রেডগুলিকে অপেক্ষার থ্রেড এবং থ্রেড উভয়ই রাজ্যে অ্যাক্সেস করা হবে, তাই এটি অবশ্যই একটি মিটেক্স দ্বারা সুরক্ষিত থাকবে। আপনি যদি মনে করেন যে আপনি একটি মুটেক্স ছাড়াই কন্ডিশন ভেরিয়েবলগুলি ব্যবহার করতে পারেন, তবে আপনি বুঝতে পারেন না যে শর্ত পরিবর্তনশীলগুলি রাষ্ট্রহীন।

কন্ডিশনের ভেরিয়েবলগুলি একটি শর্তের চারপাশে নির্মিত হয়। শর্তগুলির পরিবর্তনশীলগুলির জন্য অপেক্ষা করা থ্রেডগুলি কিছু শর্তের জন্য অপেক্ষা করছে। থ্রেডস যা সংকেত শর্তের পরিবর্তনশীলগুলি সেই অবস্থার পরিবর্তন করে। উদাহরণস্বরূপ, কোনও থ্রেড কিছু ডেটা আসার অপেক্ষায় থাকতে পারে। অন্য কিছু থ্রেড লক্ষ্য করতে পারে যে ডেটা এসেছে। "ডেটা এসেছে" শর্তটি।

শর্তের পরিবর্তনশীল, সরলীকৃত এর ক্লাসিক ব্যবহার এখানে:

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);
}

লক্ষ করুন যে কাজের সারিটি রক্ষা করতে আপনার মুটেক্সের প্রয়োজন । লক্ষ্য করুন যে কন্ডিশন ভেরিয়েবলের নিজেই ধারণা নেই যে সেখানে কাজ আছে কি না। এটি হ'ল, একটি শর্তের পরিবর্তনশীল অবশ্যই একটি শর্তের সাথে যুক্ত হতে হবে , সেই শর্তটি অবশ্যই আপনার কোড দ্বারা বজায় রাখতে হবে এবং যেহেতু এটি থ্রেডগুলির মধ্যে ভাগ করা আছে তাই এটি অবশ্যই একটি মিউেক্স দ্বারা সুরক্ষিত থাকবে।


1
অথবা, আরও সংক্ষিপ্তভাবে বলতে গেলে, অবস্থার ভেরিয়েবলগুলির সম্পূর্ণ বিন্দুটি একটি পারমাণবিক "আনলক এবং অপেক্ষা" অপারেশন সরবরাহ করা। মিউটেক্স না থাকলে আনলক করার মতো কিছুই থাকত না।
ডেভিড শোয়ার্জ

রাজ্যহীন অর্থ বোঝাতে আপনি কি আপত্তি করবেন ?
snr

@snr তাদের কোন রাজ্য নেই। তারা "লকড" বা "সিগন্যালড" বা "স্বাক্ষরবিহীন" নয়। সুতরাং শর্ত পরিবর্তনশীলের সাথে যে কোনও রাজ্যের যুক্ত কিনা তা ট্র্যাক করা আপনার দায়িত্ব। উদাহরণস্বরূপ, কন্ডিশন ভেরিয়েবল কোনও থ্রেডটি যখন কোনও সারি খালি খালি হয়ে যায় তা জানতে দেয়, তবে অবশ্যই এটি হওয়া উচিত যে একটি থ্রেডটি সারিটি খালি করে ফেলতে পারে এবং কিছু অন্য থ্রেডটি জানতে হবে যে কখন সারিটি শূন্য নয় empty এটি ভাগ করা স্থিতি, এবং আপনাকে অবশ্যই এটি একটি মিটেক্সের সাহায্যে সুরক্ষা দিতে হবে। আপনি শেকথ ভেরিয়েবলটি ওয়েটআপ মেকানিজম হিসাবে একটি মুটেক্স দ্বারা সুরক্ষিত সেই ভাগ করা রাষ্ট্রের সাথে মিল রেখে ব্যবহার করতে পারেন।
ডেভিড শোয়ার্জ

16

সমস্ত কন্ডিশনের ভেরিয়েবল ফাংশনগুলির জন্য একটি মুটেক্সের প্রয়োজন হয় না: কেবল অপেক্ষার ক্রিয়াকলাপগুলি করে। সিগন্যাল এবং সম্প্রচারের ক্রিয়াকলাপগুলির জন্য একটি মিউটেক্সের প্রয়োজন হয় না। একটি শর্ত ভেরিয়েবল স্থায়ীভাবে নির্দিষ্ট মিউটেক্সের সাথে যুক্ত হয় না; বাহ্যিক মিউটেক্স শর্ত পরিবর্তনশীলকে সুরক্ষা দেয় না। যদি শর্তের পরিবর্তনশীলটির অভ্যন্তরীণ অবস্থা থাকে যেমন অপেক্ষা অপেক্ষার থ্রেডের সারি, এটি অবশ্যই শর্ত ভেরিয়েবলের অভ্যন্তরীণ লক দ্বারা সুরক্ষিত থাকতে হবে।

অপারেশন অপারেশনগুলি একটি শর্ত পরিবর্তনশীল এবং একটি মিটেক্সকে একত্রিত করে, কারণ:

  • একটি থ্রেড মিটেক্সকে লক করেছে, ভাগ করা ভেরিয়েবলগুলির উপর কিছু অভিব্যক্তি মূল্যায়ন করেছে এবং এটি মিথ্যা বলে প্রমাণিত হয়েছে, এর জন্য এটি অপেক্ষা করতে হবে।
  • থ্রেডটি অবশ্যই নিরবচ্ছিন্নভাবে মুটেক্সের মালিকানা থেকে শর্তের অপেক্ষায় চলে যেতে হবে ।

এই কারণে ওয়েট অপারেশনটি মিউটেক্স এবং শর্ত উভয়ই যুক্তি হিসাবে গ্রহণ করে: যাতে এটি একটি থ্রেডের পারমাণবিক স্থানান্তরকে মুটেক্সের মালিক থেকে অপেক্ষার দিকে পরিচালিত করতে পারে, যাতে থ্রেডটি হারিয়ে যাওয়া জাগ্রত অবস্থার শিকার না হয় ।

একটি থ্রেড একটি মুটেক্স ছেড়ে দেয় এবং একটি স্টেটলেস সিঙ্ক্রোনাইজেশন অবজেক্টের জন্য অপেক্ষা করে, তবে একটি অ্যাটমিক নয় এমনভাবে একটি সময় উইন্ডো উপস্থিত রয়েছে: যখন থ্রেডটির আর তালা নেই, এবং আছে এখনও অবজেক্টের জন্য অপেক্ষা শুরু না। এই উইন্ডোর সময়, অন্য থ্রেড আসতে পারে, প্রতীক্ষিত শর্তটিকে সত্য করে তুলতে পারে, রাষ্ট্রবিহীন সিঙ্ক্রোনাইজেশনের সংকেত দেয় এবং তারপরে অদৃশ্য হয়ে যায়। রাষ্ট্রবিহীন বস্তু মনে রাখে না যে এটি সংকেত ছিল (এটি রাষ্ট্রবিহীন)। সুতরাং তারপরে মূল থ্রেডটি স্টেটলেস সিঙ্ক্রোনাইজেশন অবজেক্টে ঘুমাতে যায় এবং জাগ্রত হয় না, যদিও এটির শর্তটি ইতিমধ্যে সত্য হয়ে গেছে: হারিয়ে যাওয়া জাগ্রত।

কন্ডিশন ভেরিয়েবল ওয়েট ফাংশনগুলি মুটিেক্সটি ছাড়ার আগে কলিং থ্রেডটি নির্ভরযোগ্যভাবে ওয়েকআপটি ধরার জন্য নিবন্ধিত হয়েছে কিনা তা নিশ্চিত করে হারানো জাগাটি এড়াতে পারে। শর্ত পরিবর্তনশীল ওয়েট ফাংশনটি মিউটেক্সটিকে আর্গুমেন্ট হিসাবে গ্রহণ না করলে এটি অসম্ভব।


আপনি কি রেফারেন্স সরবরাহ করতে পারেন যে সম্প্রচার ক্রিয়াকলাপগুলিকে মুটেক্স অর্জনের প্রয়োজন হয় না? এমএসভিসিতে সম্প্রচার উপেক্ষা করা হয়।
xvan

@ এক্সওয়ান পসিক্স pthread_cond_broadcastএবং pthread_cond_signalক্রিয়াকলাপগুলি (যে এই প্রশ্নটি সম্পর্কে প্রশ্ন রয়েছে) এমনকি মুটেক্সকে আর্গুমেন্ট হিসাবে গ্রহণ করে না; শুধুমাত্র শর্ত পসিক্স স্পেকটি এখানে রয়েছে । তারা জেগে ওঠার অপেক্ষায় থাকা থ্রেডগুলিতে কী ঘটে যায় কেবল সেই রেফারেন্সে মিউটেক্সটি উল্লেখ করা হয়।
কাজ

রাজ্যহীন অর্থ বোঝাতে আপনি কি আপত্তি করবেন ?
snr

1
@ এসএনআর একটি স্টেটলেস সিঙ্ক্রোনাইজেশন অবজেক্ট সংকেত সম্পর্কিত কোনও রাষ্ট্রের কথা মনে রাখে না। যখন সংকেত দেওয়া হয়, এখন যদি কিছু এটির জন্য অপেক্ষা করে থাকে তবে তা জেগে যায়, অন্যথায় জাগরণটি ভুলে যায়। কন্ডিশনের ভেরিয়েবলগুলি এর মতো স্টেটলেস। সিঙ্ক্রোনাইজেশনকে নির্ভরযোগ্য করে তুলতে প্রয়োজনীয় রাষ্ট্রটি অ্যাপ্লিকেশন দ্বারা বজায় রাখা হয় এবং মুটিেক্স দ্বারা সুরক্ষিত হয় যা সঠিকভাবে লিখিত যুক্তি অনুসারে শর্ত ভেরিয়েবলের সাথে একত্রে ব্যবহৃত হয়।
কাজ

7

অন্যান্য উত্তরগুলি এই পৃষ্ঠার মতো সংক্ষিপ্ত এবং পাঠযোগ্য হিসাবে খুঁজে পাচ্ছি না । সাধারণত ওয়েটিং কোডটি এরকম কিছু দেখায়:

mutex.lock()
while(!check())
    condition.wait()
mutex.unlock()

wait()নিঃশব্দে মোড়ানোর জন্য তিনটি কারণ রয়েছে :

  1. মিউটেক্স ছাড়াই অন্য কোনও থ্রেড signal()আগে উঠতে পারে wait()এবং আমরা এই জাগ্রত অনুভব করতে চাই।
  2. সাধারণত check()অন্য থ্রেড থেকে পরিবর্তনের উপর নির্ভরশীল, সুতরাং যাইহোক এটির ক্ষেত্রে আপনার পারস্পরিক বর্জন প্রয়োজন।
  3. সর্বোচ্চ অগ্রাধিকারের থ্রেডটি প্রথমে এগিয়ে চলেছে তা নিশ্চিত করতে (মুটেক্সের সারিটি শিডিয়ুলার কে কে এগিয়ে যায় তা সিদ্ধান্ত নিতে দেয়)।

তৃতীয় বিষয়টি সর্বদা উদ্বেগের বিষয় নয় - historicalতিহাসিক প্রসঙ্গটি নিবন্ধ থেকে এই কথোপকথনের সাথে লিঙ্কযুক্ত ।

উদ্দীপনা জাগ্রত করার বিষয়টি প্রায়শই এই প্রক্রিয়াটির সাথে উল্লেখ করা হয় (অর্থাত্ অপেক্ষার থ্রেডটি signal()না ডেকে জেগে থাকে )। যাইহোক, এই জাতীয় ইভেন্টগুলি লুপেড দ্বারা পরিচালিত হয় check()


4

কন্ডিশনের ভেরিয়েবলগুলি একটি মুটেক্সের সাথে যুক্ত কারণ এটি এড়াতে পারে এমন একমাত্র উপায় যা এড়ানোর জন্য ডিজাইন করা হয়েছে।

// 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);

3

আপনি কল করার সময় মুটেক্সটি লক হওয়ার কথা pthread_cond_wait; আপনি যখন এটিকে ডাকছেন তখন উভয়ই শ্বেতকে তালাবদ্ধ করে এবং শর্তটি বন্ধ করে দেয়। শর্তটি সংকেত দেওয়া হয়ে গেলে এটি পরমাণুভাবে আবার এটি লক করে ফিরে আসে।

এটি যদি ইচ্ছা হয় তবে পূর্বাভাসযোগ্য সময়সূচী বাস্তবায়নের অনুমতি দেয়, যে থ্রেডটি যে সিগন্যালিং করে তা মুটেক্সটি প্রক্রিয়াজাতকরণের জন্য অপেক্ষা করতে পারে এবং তারপরে শর্তটি সংকেত দেয়।


সুতরাং… আমার কাছে এমন কোনও কারণ আছে যা কেবলমাত্র মিটেক্সকে সর্বদা আনলক করা না রেখে, এবং তারপরে অপেক্ষা করার আগে ডানদিকে তালাবন্ধ করে রাখা, এবং তারপরে অপেক্ষা শেষ হওয়ার পরে এটি আনলক করা উচিত?
এলিওটিটিসিবল

মিউটেক্স ওয়েটিং এবং সিগন্যালিং থ্রেডগুলির মধ্যে কিছু সম্ভাব্য রেসগুলিও সমাধান করে। শর্ত পরিবর্তন এবং সিগন্যাল করার সময় যতক্ষণ না মিউটেক্স সর্বদা তালাবদ্ধ থাকে, আপনি কখনই নিজেকে সিগন্যালটি হারিয়ে এবং চিরকালের জন্য ঘুমিয়ে দেখতে পাবেন না
হস্তুরকুন

সুতরাং… কন্ডিশনভারের অপেক্ষা করার আগে আমার প্রথমে কন্ডিশনভারের মিটেক্সে অপেক্ষা করা উচিত ? আমি নিশ্চিত যে আমি আদৌ বুঝতে পারি না।
এলিওটিটিসিবল

2
@ এলিওটেকটেবল: মিটেক্স না ধরে আপনি কীভাবে জানতে পারবেন যে আপনার অপেক্ষা করা উচিত নয় বা করা উচিত নয়? আপনি যদি অপেক্ষা করছেন যা সবেমাত্র ঘটেছিল?
ডেভিড শোয়ার্জ

1

আপনি যদি শর্ত পরিবর্তনের প্রকৃত উদাহরণ চান তবে আমি ক্লাসে একটি অনুশীলন করেছি:

#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);
}

1

এটি ধারণাগত প্রয়োজনের চেয়ে একটি নির্দিষ্ট নকশার সিদ্ধান্ত হিসাবে প্রতীয়মান।

প্রতি পাইথ্রেডস ডকস অনুসারে মিউটেক্সটি আলাদা না হওয়ার কারণ হ'ল তাদের একত্রিত করার মাধ্যমে একটি উল্লেখযোগ্য পারফরম্যান্স উন্নতি হয়েছে এবং তারা আশা করেন যে সাধারণ জাতি অবস্থার কারণে আপনি যদি কোনও মিটেক্স ব্যবহার না করেন তবে এটি প্রায় সর্বদা যাইহোক সম্পন্ন হবে।

https://linux.die.net/man/3/pthread_cond_wait

শব্দের বৈশিষ্ট্য এবং শর্ত ভেরিয়েবলগুলি

পরামর্শ দেওয়া হয়েছিল যে শর্ত অপেক্ষা থেকে মুটেক্স অধিগ্রহণ এবং রিলিজ হ্রাস পাবে। এটি প্রত্যাখ্যান করা হয়েছিল কারণ এটি অপারেশনের সম্মিলিত প্রকৃতি যা বাস্তবে রিয়েলটাইম বাস্তবায়ন সহজতর করে। এই বাস্তবায়নগুলি কমনীয়ভাবে শর্ত পরিবর্তনশীল এবং মিউটেক্সের মধ্যে এমনভাবে একটি উচ্চ-অগ্রাধিকারের থ্রেডকে কল করতে পারে যা কলারের কাছে স্বচ্ছ। এটি অতিরিক্ত প্রসঙ্গের স্যুইচগুলি প্রতিরোধ করতে পারে এবং অপেক্ষার থ্রেডটি সিগন্যাল করা হলে একটি মিটেক্সের আরও নির্ধারিত অধিগ্রহণ সরবরাহ করতে পারে। সুতরাং, সুষ্ঠুতা এবং অগ্রাধিকার সংক্রান্ত সমস্যাগুলি সিডিয়ুলিং শৃঙ্খলা দ্বারা সরাসরি মোকাবিলা করা যেতে পারে। তদতিরিক্ত, বর্তমান শর্ত অপেক্ষা অপারেশন বিদ্যমান অনুশীলনের সাথে মেলে।


0

সে সম্পর্কে একাধিক ছাড় রয়েছে, তবুও আমি নিম্নলিখিত উদাহরণ দিয়ে এটিকে প্রকাশ করতে চাই।

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 করা হয়। যখন পিতামাতারা আবার দৌড়ান, তখন এটি চিরকাল ঘুমায়, যা সত্যই অত্যন্ত উদ্বেগজনক।

যদি আলাদাভাবে লকগুলি অর্জন করার সময় সেগুলি সম্পাদন করা হয় তবে কী হবে?

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.