কেন অপেক্ষা করতে হবে () সর্বদা সিঙ্ক্রোনাইজড ব্লকে থাকতে হবে


257

আমরা সকলেই জানি যে প্রার্থনা করার জন্য Object.wait(), এই কলটি অবশ্যই সিঙ্ক্রোনাইজড ব্লকে রাখা উচিত, অন্যথায় একটি IllegalMonitorStateExceptionনিক্ষিপ্ত হয়। তবে এই বাধা দেওয়ার কারণ কী? আমি জানি যে wait()মনিটরটি মুক্তি দেয় তবে কেন আমাদের স্পষ্টভাবে নির্দিষ্ট ব্লককে সিঙ্ক্রোনাইজ করে মনিটরটি অর্জন করার এবং তারপরে কল করে মনিটরটি প্রকাশ করা দরকার wait()?

যদি wait()কোনও সিঙ্ক্রোনাইজড ব্লকের বাইরে ডাকার পক্ষে শব্দার্থকতা ধরে রাখা - কলারের থ্রেড স্থগিত করা সম্ভব হয় তবে সম্ভাব্য ক্ষতি কী ?

উত্তর:


232

একটি wait()কেবল তখনই বোঝা যায় যখন একটি থাকে notify(), সুতরাং এটি সর্বদা থ্রেডগুলির মধ্যে যোগাযোগ সম্পর্কে এবং সঠিকভাবে কাজ করার জন্য এটির জন্য সিঙ্ক্রোনাইজেশন প্রয়োজন। যে কেউ যুক্তি দিতে পারে যে এটি অন্তর্নিহিত হওয়া উচিত, তবে এটি সত্যিকারের সাহায্য করবে না, নিম্নলিখিত কারণে:

শব্দার্থকভাবে, আপনি কখনও না wait()। আপনার সন্তুষ্ট হওয়ার জন্য কিছু শর্ত প্রয়োজন এবং এটি যদি না হয় তবে আপনি এটি না হওয়া পর্যন্ত অপেক্ষা করুন। সুতরাং আপনি কি সত্যিই কি

if(!condition){
    wait();
}

তবে শর্তটি একটি পৃথক থ্রেড দ্বারা সেট করা হচ্ছে, সুতরাং এই কাজটি সঠিকভাবে করার জন্য আপনার সিঙ্ক্রোনাইজেশন প্রয়োজন।

এটির সাথে আরও দু'টি জিনিস ভুল রয়েছে, কেবলমাত্র আপনার থ্রেড অপেক্ষা করা ছেড়ে দেওয়ার অর্থ এই নয় যে আপনি যে শর্তটি খুঁজছেন তা সত্য:

  • আপনি উত্সাহী জাগ্রতগুলি পেতে পারেন (যার অর্থ কোনও থ্রেড কোনও বিজ্ঞপ্তি না পেয়ে অপেক্ষা করা থেকে জেগে উঠতে পারে), বা

  • শর্তটি সেট হয়ে যেতে পারে, তবে তৃতীয় থ্রেডটি অপেক্ষার থ্রেড জেগে ওঠার সাথে সাথে শর্তটিকে আবার মিথ্যা করে তোলে (এবং মনিটরের প্রতিক্রিয়া জানায়)।

এই ক্ষেত্রে মোকাবেলা করার জন্য আপনার যা দরকার তা হ'ল সর্বদা এর কিছু প্রকরণ:

synchronized(lock){
    while(!condition){
        lock.wait();
    }
}

আরও ভাল, সিঙ্ক্রোনাইজেশন আদিমগুলিতে মোটেও গণ্ডগোল করবেন না এবং java.util.concurrentপ্যাকেজগুলিতে প্রদত্ত বিমূর্তিগুলি নিয়ে কাজ করুন ।


3
মূলত একই জিনিসটি বলতে এখানেও একটি বিশদ আলোচনা আছে। কোডিং.আরডকিলার.আরচাইভ

1
বিটিডব্লিউ, আপনি যদি বাধা দেওয়া পতাকাটিকে অগ্রাহ্য না করেন তবে লুপটিও পরীক্ষা করতে হবে Thread.interrupted()
বেসটস

2
আমি এখনও এর মতো কিছু করতে পারি: যখন (! শর্ত) {সিঙ্ক্রোনাইজড (এটি) {অপেক্ষা ();} means যার অর্থ শর্তটি পরীক্ষা করা এবং অপেক্ষা () অপেক্ষা সঠিকভাবে একটি সিঙ্ক্রোনাইজড ব্লকে বলা হলেও অপেক্ষা করার মধ্যে একটি প্রতিযোগিতা রয়েছে। তাহলে এই বিধিনিষেধের পিছনে অন্য কোনও কারণ রয়েছে, সম্ভবত এটি জাভাতে বাস্তবায়িত হওয়ার কারণে?
shrini1000

9
আরেকটি বাজে পরিস্থিতি: শর্তটি মিথ্যা, আমরা অপেক্ষা করতে যাচ্ছি () এবং তারপরে অন্য একটি থ্রেড শর্ত পরিবর্তন করে এবং বিজ্ঞপ্তি () কে অনুরোধ করে। কারণ আমরা এখনও অপেক্ষা করতে পারি না (), আমরা এই বিজ্ঞপ্তিটি () মিস করব miss অন্য কথায়, পরীক্ষা এবং অপেক্ষা, পাশাপাশি পরিবর্তন এবং বিজ্ঞপ্তি অবশ্যই পারমাণবিক হতে হবে ।

1
@ নলপোয়েন্টার: যদি এটি আ টাইপ হয় যা পরমাণুভাবে লেখা যেতে পারে (যেমন বুলিয়ান সরাসরি এটি যদি ক্লজ-এ ব্যবহার করে বোঝানো হয়) এবং অন্যান্য ভাগ করা ডেটার সাথে কোনও আন্তঃনির্ভরতা না থাকে, আপনি এটিকে অস্থির ঘোষণা করে পালিয়ে যেতে পারেন। তবে আপডেটটি অন্য থ্রেডে তাত্ক্ষণিকভাবে দৃশ্যমান হবে তা নিশ্চিত করার জন্য আপনার যেটি বা সিঙ্ক্রোনাইজেশন প্রয়োজন।
মাইকেল বর্গওয়ার্ট

282

যদি wait()কোনও সিঙ্ক্রোনাইজড ব্লকের বাইরে ডাকার পক্ষে শব্দার্থকতা ধরে রাখা - কলারের থ্রেড স্থগিত করা সম্ভব হয় তবে সম্ভাব্য ক্ষতি কী ?

আসুন চিত্রিত করা যাক আমরা কোন সমস্যাগুলিতে চলে যাব যদি wait()একটি সিঙ্ক্রোনাইজড ব্লকের বাইরে কোনও কংক্রিটের উদাহরণ সহ কল ​​করা যায়

মনে করুন আমরা একটি ব্লকিং সারিটি প্রয়োগ করছিলাম (আমি জানি, এপিআইতে ইতিমধ্যে একটি রয়েছে :)

প্রথম প্রচেষ্টা (সিঙ্ক্রোনাইজেশন ছাড়াই) নীচের লাইনের সাথে কিছু দেখতে পেল

class BlockingQueue {
    Queue<String> buffer = new LinkedList<String>();

    public void give(String data) {
        buffer.add(data);
        notify();                   // Since someone may be waiting in take!
    }

    public String take() throws InterruptedException {
        while (buffer.isEmpty())    // don't use "if" due to spurious wakeups.
            wait();
        return buffer.remove();
    }
}

এটিই সম্ভাব্যভাবে ঘটতে পারে:

  1. একটি গ্রাহক থ্রেড কল করে take()দেখে buffer.isEmpty()

  2. গ্রাহক থ্রেড কল করার আগে wait(), একটি প্রযোজক থ্রেড বরাবর আসে এবং একটি পূর্ণ give(), অর্থাৎ,buffer.add(data); notify();

  3. ভোক্তা থ্রেড এখন ডাকব wait()(এবং মিস্notify() যে শুধু বলা হত)।

  4. যদি দুর্ভাগ্য হয় give()তবে গ্রাহক থ্রেড কখনই জেগে ওঠে না এবং ফলস্বরূপ আমাদের কাছে একটি ডেড-লক রয়েছে বলে ফলক হিসাবে উত্পাদক থ্রেড বেশি উত্পাদন করতে পারে না ।

আপনি একবার সমস্যাটি বুঝতে পারলে সমাধানটি সুস্পষ্ট: synchronizedনিশ্চিত হওয়ার জন্য ব্যবহার notifyকখনই isEmptyএবং এর মধ্যে কখনও ডাকা হয় না wait

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


@ উইলির পোস্ট করা লিঙ্কের একটি অনুচ্ছেদে এটির সংক্ষিপ্তসার জানানো হয়েছে:

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

উত্পাদক এবং ভোক্তা যে বিষয়ে পোষ মানতে চান তা উপরের উদাহরণে রয়েছে buffer.isEmpty()। এবং চুক্তিটি synchronizedব্লকগুলিতে অপেক্ষা ও বিজ্ঞপ্তি সম্পাদিত হয় তা নিশ্চিত করে সমাধান করা হয়।


এই পোস্টটি এখানে একটি নিবন্ধ হিসাবে আবার লেখা হয়েছে: জাভা: কেন অপেক্ষা করতে হবে একটি সিঙ্ক্রোনাইজড ব্লকে ডাকতে হবে


অপেক্ষার () কাজ শেষ হওয়ার সাথে সাথে শর্তে পরিবর্তনগুলি তত্ক্ষণাত দেখা যায় তা নিশ্চিত করার জন্যও আমার ধারণা। অন্যথায়, বিজ্ঞপ্তি () ইতিমধ্যে কল করার পরেও একটি মৃত-লক রয়েছে।
সূর্য বিজয়া মাদজিদ

আকর্ষণীয়, তবে মনে রাখবেন যে কেবলমাত্র সিঙ্ক্রোনাইজ করা কলটি "অবিশ্বাস্য" প্রকৃতির অপেক্ষা () এবং বিজ্ঞপ্তি () এর কারণে এই জাতীয় সমস্যাগুলি সবসময় সমাধান করবে না। এখানে আরও পড়ুন: স্ট্যাকওভারফ্লো / প্রশ্নগুলি / 21439355/… । কেন সিঙ্ক্রোনাইজ করা প্রয়োজন তা হার্ডওয়্যার আর্কিটেকচারের মধ্যে রাখে (নীচে আমার উত্তর দেখুন)।
মার্কাস

তবে return buffer.remove();ব্লক করার পরে কিন্তু পরে যুক্ত হলে wait();, এটি কাজ করে?
ববজিয়াং

@ বোবিজিয়াং, না, কেউ কল দেওয়ার চেয়ে অন্য কারণে থ্রেড জাগ্রত হতে পারে। অন্য কথায়, বাফারটি waitরিটার্নের পরেও খালি থাকতে পারে ।
আইয়ুব

আমি শুধু আছে Thread.currentThread().wait();mainফাংশন জন্য ব্যবহার করে দেখুন-ধরা দ্বারা বেষ্টিত InterruptedExceptionsynchronizedব্লক ছাড়াই , এটি আমাকে একই ব্যতিক্রম দেয় IllegalMonitorStateException। এটি এখন অবৈধ অবস্থায় পৌঁছায় কি করে? এটি synchronizedযদিও ব্লকের ভিতরে কাজ করে ।
শাশ্বত

12

@ রোলারবল ঠিক আছে। wait()বলা হয়, যাতে থ্রেড ঘটতে যখন এই কিছু অবস্থার জন্য অপেক্ষা করতে পারেন wait()কল, এরকম থ্রেড তার লক ছেড়ে দিতে বাধ্য হয়।
কিছু ছেড়ে দিতে, আপনার প্রথমে এটি মালিকানাধীন হওয়া দরকার। থ্রেডটির প্রথমে লকের মালিক হওয়া দরকার। সুতরাং এটি একটি synchronizedপদ্ধতি / ব্লকের ভিতরে কল করার প্রয়োজন ।

হ্যাঁ, আপনি যদি synchronizedপদ্ধতি / ব্লকের মধ্যে শর্তটি পরীক্ষা না করেন তবে সম্ভাব্য ক্ষয়ক্ষতি / অসঙ্গতিগুলি সম্পর্কে উপরের সমস্ত উত্তরের সাথে আমি একমত । যাইহোক @ shrini1000 উল্লেখ করেছেন যে, কেবল wait()সিঙ্ক্রোনাইজড ব্লকের মধ্যে কল করা এই অসঙ্গতিটিকে ঘটতে বাধা দেবে না।

এখানে একটি সুন্দর পড়া ..


5
@ পোপে সঠিকভাবে 'সঠিকভাবে' ব্যাখ্যা করুন। আপনার মন্তব্য কারও কাজে আসেনি।
লার্নের মার্কুইস

4

আপনি পূর্বে সিঙ্ক্রোনাইজ না করলে এটির কারণ হতে পারে wait():

  1. যদি প্রথম থ্রেডটি makeChangeOnX()andুকে গিয়ে কিছুক্ষণ শর্তটি পরীক্ষা করে এবং এটি হয় true( x.metCondition()রিটার্ন false, মানে x.conditionহয় false) তাই এটি এর ভিতরে আসবে। তারপর শুধু সামনে wait()পদ্ধতি, অন্য থ্রেড যায় setConditionToTrue()এবং সেট x.conditionকরার trueএবং notifyAll()
  2. তারপরে কেবল তার পরে, 1 ম থ্রেডটি তার wait()পদ্ধতিতে প্রবেশ করবে ( notifyAll()কয়েক মুহুর্তের আগে এর দ্বারা প্রভাবিত হয়নি )। এই ক্ষেত্রে, 1 ম থ্রেডটি অন্য থ্রেডটি সম্পাদনের জন্য অপেক্ষা করবে setConditionToTrue(), তবে সম্ভবত এটি আবার না ঘটে।

তবে আপনি যদি synchronizedসেই পদ্ধতির আগে রাখেন যা বস্তুর স্থিতি পরিবর্তন করে, এটি ঘটবে না।

class A {

    private Object X;

    makeChangeOnX(){
        while (! x.getCondition()){
            wait();
            }
        // Do the change
    }

    setConditionToTrue(){
        x.condition = true; 
        notifyAll();

    }
    setConditionToFalse(){
        x.condition = false;
        notifyAll();
    }
    bool getCondition(){
        return x.condition;
    }
}

2

আমরা সকলেই জানি যে আন্তঃ-থ্রেড যোগাযোগের জন্য অপেক্ষা (), বিজ্ঞপ্তি () এবং বিজ্ঞপ্তি (সমস্ত) পদ্ধতি ব্যবহার করা হয়। মিসড সিগন্যাল এবং উত্সাহী জাগ্রত সমস্যা থেকে মুক্তি পেতে অপেক্ষার থ্রেড সর্বদা কিছু শর্তের জন্য অপেক্ষা করে। eg-

boolean wasNotified = false;
while(!wasNotified) {
    wait();
}

তারপরে থ্রেড সেটগুলি বিজ্ঞাপিত করা হয়েছে সত্য এবং বিজ্ঞাপিতের পরিবর্তিত পরিবর্তনশীল।

প্রতিটি থ্রেডের স্থানীয় ক্যাশে থাকে তাই সমস্ত পরিবর্তনগুলি প্রথমে সেখানে লেখা হয় এবং পরে ধীরে ধীরে মূল স্মৃতিতে প্রচার করা হয়।

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

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

synchronized(monitor) {
    boolean wasNotified = false;
    while(!wasNotified) {
        wait();
    }
}

ধন্যবাদ, আশা করি এটি স্পষ্ট হয়েছে।


1

এটি মূলত হার্ডওয়্যার আর্কিটেকচার (যেমন র‌্যাম এবং ক্যাশে ) এর সাথে সম্পর্কিত।

আপনি ব্যবহার না করেন তাহলে synchronizedএকসাথে wait()বা notify()আরেকটি থ্রেড পারে পরিবর্তে মনিটর প্রবেশ জন্য অপেক্ষা একই ব্লক লিখুন। তাছাড়া, যখন একজন সিঙ্ক্রোনাইজ ব্লক ছাড়া একটি অ্যারের অ্যাক্সেস the, অন্য থ্রেড না এটি changement দেখতে পারেন ... আসলে অন্য থ্রেড করা হবে না এটি কোন changements দেখতে যখন এটি আগে থেকেই এক্স-স্তর ক্যাশের মধ্যে অ্যারের একটি কপি আছে ( থ্রেড হ্যান্ডলিং সিপিইউ কোর এর প্রথম / দ্বিতীয় / দ্বিতীয় তৃতীয় স্তরের ক্যাশে)।

তবে সিঙ্ক্রোনাইজড ব্লকগুলি পদকের একমাত্র দিক: আপনি যদি অ-সিঙ্ক্রোনাইজ করা প্রসঙ্গ থেকে একটি সিঙ্ক্রোনাইজ করা প্রসঙ্গের মধ্যে আসলে কোনও বস্তু অ্যাক্সেস করেন তবে অবজেক্টটি এখনও একটি সিঙ্ক্রোনাইজড ব্লকের মধ্যে সিঙ্ক্রোনাইজ হবে না, কারণ এটির একটি নিজস্ব অনুলিপি রয়েছে তার ক্যাশে অবজেক্ট। আমি এই সমস্যাগুলি সম্পর্কে এখানে লিখেছি: https://stackoverflow.com/a/21462631 এবং যখন কোনও লক একটি চূড়ান্ত অবজেক্ট ধারণ করে, তখনও কি বস্তুর রেফারেন্সটি অন্য থ্রেড দ্বারা পরিবর্তন করা যেতে পারে?

তদুপরি, আমি নিশ্চিত যে এক্স-লেভেল ক্যাশে বেশিরভাগ অ-প্রজননযোগ্য রানটাইম ত্রুটির জন্য দায়ী। এর কারণ বিকাশকারীরা সাধারণত নিম্ন-স্তরের স্টাফগুলি শিখেন না, যেমন সিপিইউর কাজ কীভাবে বা মেমরির শ্রেণিবিন্যাস কীভাবে অ্যাপ্লিকেশনগুলির চলমানতাকে প্রভাবিত করে: http://en.wikedia.org/wiki/Memory_hierarchy

প্রোগ্রামিং ক্লাসগুলি কেন প্রথমে মেমরি হায়ারার্কি এবং সিপিইউ আর্কিটেকচার দিয়ে শুরু হয় না এটি একটি ধাঁধা থেকেই যায়। "হ্যালো ওয়ার্ল্ড" এখানে সাহায্য করবে না। ;)



হুম .. নিশ্চিত না আমি অনুসরণ করি। যদি ক্যাচিংয়ের জন্য সিঙ্ক্রোনাইজের ভিতরে অপেক্ষা এবং বিজ্ঞপ্তি দেওয়ার একমাত্র কারণ ছিল, তবে কেন অপেক্ষা / নোটিফিকেশন প্রয়োগের ভিতরে সিঙ্ক্রোনাইজেশন রাখা হয়নি?
আইয়ুব

ভাল প্রশ্ন, যেহেতু অপেক্ষা / বিজ্ঞপ্তিটি খুব ভালভাবে সিঙ্ক্রোনাইজড পদ্ধতিগুলি হতে পারে ... সূর্যের প্রাক্তন জাভা বিকাশকারীরা উত্তর জানেন? উপরের লিঙ্কটি একবার দেখুন বা সম্ভবত এটি আপনাকে সহায়তা করবে: ডকস.ওরকল
মার্কাস

একটি কারণ হতে পারে: জাভা শুরুর দিনগুলিতে এই মাল্টিথ্রেডিং ক্রিয়াকলাপগুলি করার আগে সিঙ্ক্রোনাইজ করা কল না করার সময় কোনও সংকলন ত্রুটি ছিল না। পরিবর্তে কেবলমাত্র রানটাইম ত্রুটি ছিল (যেমন কোডরঞ্চ . com/t/239491/java-programmer-SCJP/cerificationsation/… )। হতে পারে তারা সত্যিই @ সানকে ভেবেছিল যে প্রোগ্রামাররা যখন এই ত্রুটিগুলি পাচ্ছে তখন তাদের সাথে যোগাযোগ করা হচ্ছে, যা তাদের বেশিরভাগ সার্ভার বিক্রি করার সুযোগ দিয়েছে। কখন বদলে গেল? জাভা 5.0 বা 6.0 হতে পারে, তবে আসলে আমি মনে করি সৎ হতে হবে না ...
মার্কাস

টিবিএইচ আমি আপনার উত্তর সহ কয়েকটি সমস্যা দেখতে পাচ্ছি 1) আপনার দ্বিতীয় বাক্যটি বোঝা যায় না: কোন থ্রেডে কোন বস্তু লক হয়েছে তা বিবেচ্য নয়। দুটি থ্রেড কী সিলেক্ট করতে পারে তা নির্বিশেষে সমস্ত পরিবর্তন দৃশ্যমান হয়। 2) আপনি বলছেন যে অন্য থ্রেড "দেখবে" কোনও পরিবর্তন দেখবে না । এটি "নাও হতে পারে " হওয়া উচিত । 3) আমি জানি না আপনি কেন 1 ম / 2 য় / 3 য় স্তরের ক্যাশে আনছেন ... এখানে জাভা মেমোরি মডেল কী বলে তা জেএলএস-এ নির্দিষ্ট করা আছে specified যদিও হার্ডওয়্যার আর্কিটেকচার জেএলএস কেন এটি বলে তা বুঝতে সহায়তা করতে পারে , তবে এই প্রসঙ্গে কঠোরভাবে অপ্রাসঙ্গিক কথা বলছে।
আইওবে

0

সরাসরি এই জাভা ওরাকল টিউটোরিয়াল থেকে:

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


লেখক যে প্রশ্নটি করেছেন, তা থেকে মনে হয় না যে আমি টিউটোরিয়ালটি থেকে কী উদ্ধৃত করেছি সে সম্পর্কে প্রশ্ন লেখকের স্পষ্ট ধারণা রয়েছে। এবং তদুপরি আমার উত্তরটি "কেন" ব্যাখ্যা করে।
রোলারবল

0

আপনি যখন কোনও অবজেক্ট টি থেকে নোটিফাই () কল করেন, জাভা একটি নির্দিষ্ট t.wait () পদ্ধতিটি অবহিত করে। তবে, জাভা কীভাবে একটি নির্দিষ্ট অপেক্ষা পদ্ধতি অনুসন্ধান করে এবং অবহিত করে।

জাভা কেবল কোডের সিঙ্ক্রোনাইজড ব্লকটিতে অনুসন্ধান করে যা অবজেক্ট টি দ্বারা লক করা হয়েছিল। জাভা কোনও নির্দিষ্ট t.wait () কে অবহিত করার জন্য পুরো কোডটি অনুসন্ধান করতে পারে না।


0

ডক্স অনুসারে:

বর্তমান থ্রেডে অবশ্যই এই বস্তুর মনিটরের মালিক হতে হবে। থ্রেড এই মনিটরের মালিকানা প্রকাশ করে।

wait()পদ্ধতির সহজ অর্থ এটি বস্তুর উপর লক প্রকাশ করে। সুতরাং অবজেক্টটি কেবল সিঙ্ক্রোনাইজড ব্লক / পদ্ধতির মধ্যেই লক হয়ে যাবে। থ্রেডটি যদি সিঙ্ক ব্লকের বাইরে থাকে মানে এটি লক করা নেই, যদি এটি লক না করা থাকে তবে আপনি কী অবজেক্টে প্রকাশ করবেন?


0

মনিটরিং অবজেক্টের থ্রেড ওয়েট (সিঙ্ক্রোনাইজেশন ব্লক দ্বারা ব্যবহৃত বস্তু), একক থ্রেডের পুরো যাত্রায় মনিটরিং অবজেক্টের সংখ্যা থাকতে পারে। যদি থ্রেড সিঙ্ক্রোনাইজেশন ব্লকের বাইরে অপেক্ষা করে তবে সেখানে কোনও মনিটরিং অবজেক্ট নেই এবং মনিটরিং অবজেক্টের অ্যাক্সেসের জন্য অন্যান্য থ্রেডকেও বিজ্ঞপ্তি দেওয়া হয়েছে, সুতরাং সিঙ্ক্রোনাইজেশন ব্লকের বাইরে থাকা থ্রেডটি কীভাবে জানবে যে এটি অবহিত হয়েছে। থ্রেড ক্লাসের পরিবর্তে অবজেক্ট (), notify () এবং notifyAll () অবজেক্ট ক্লাসে থাকায় এটি অন্যতম কারণ।

মূলত মনিটরিং অবজেক্টটি এখানে সমস্ত থ্রেডের সাধারণ সংস্থান এবং মনিটরিং অবজেক্টগুলি কেবল সিঙ্ক্রোনাইজেশন ব্লকে উপলব্ধ।

class A {
   int a = 0;
  //something......
  public void add() {
   synchronization(this) {
      //this is your monitoring object and thread has to wait to gain lock on **this**
       }
  }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.