জাভাতে উত্সাহী জাগরণগুলি কি আসলে ঘটে?


208

বিভিন্ন লক সম্পর্কিত প্রশ্ন দেখে এবং (প্রায়) সর্বদা 'উত্সাহযুক্ত জাগরণের কারণে লুপটি খুঁজে পাওয়া যায় " 1 আমি অবাক করে বলছি, কেউ কি এই জাতীয় ধরণের ওয়েকআপ (উদাহরণস্বরূপ একটি শালীন হার্ডওয়্যার / সফ্টওয়্যার পরিবেশ ধরে) অনুভব করেছেন?

আমি জানি 'স্পিউরিয়াস' শব্দটির অর্থ কোনও আপাত কারণ নয় তবে এই জাতীয় ঘটনার কারণগুলি কী হতে পারে?

( 1 দ্রষ্টব্য: আমি লুপিং অনুশীলন নিয়ে প্রশ্ন করছি না))

সম্পাদনা করুন: একটি সহায়ক প্রশ্ন (যারা কোড নমুনা পছন্দ করেন তাদের জন্য):

আমার যদি নিম্নলিখিত প্রোগ্রাম থাকে এবং আমি এটি চালাও:

public class Spurious {
    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        Condition cond = lock.newCondition();
        lock.lock();
        try {
            try {
                cond.await();
                System.out.println("Spurious wakeup!");
            } catch (InterruptedException ex) {
                System.out.println("Just a regular interrupt.");
            }
        } finally {
            lock.unlock();
        }
    }
}

awaitএলোমেলোভাবে ঘটনার জন্য চিরকাল অপেক্ষা না করে এটিকে জাগ্রত করতে আমি কী করতে পারি ?


1
পভিসআইক্স সিস্টেমগুলিতে চালিত এবং pthread_cond_wait()আসল প্রশ্নটি ব্যবহার করে এমন জেভিএমগুলির জন্য "pthread_cond_wait এর কেন উত্সাহী জাগরণ রয়েছে?"
ফ্লো

উত্তর:


204

উত্সাহী জাগরণের বিষয়ে উইকিপিডিয়া নিবন্ধটিতে এই বিবৃতি রয়েছে:

pthread_cond_wait()Linux এ ফাংশন ব্যবহার করে বাস্তবায়িত হয় futexসিস্টেম কল। EINTRপ্রক্রিয়াটি সংকেত পেলে লিনাক্সের প্রতিটি ব্লকিং সিস্টেম কল হঠাৎ করে ফিরে আসে । ... pthread_cond_wait()অপেক্ষার পুনরায় আরম্ভ করতে পারবেন না কারণ এটি futexসিস্টেম কলের বাইরে থাকা অল্প সময়েই একটি সত্যিকারের জাগানো অনুভব করতে পারে । এই রেস শর্তটি কেবলমাত্র একজন আক্রমণকারীকে পরীক্ষা করার জন্য কলার দ্বারা এড়ানো যায়। একটি পসিক্স সিগন্যাল অতএব উত্সাহী জাগ্রত তৈরি করবে।

সারাংশ : লিনাক্স প্রক্রিয়া তার অপেক্ষা থ্রেড সংকেত দেওয়া হয় তবে প্রতিটি একটা চমৎকার, গরম ভোগ করবে কৃত্রিম ওয়েকআপ

আমি এটা কিনব. এটি প্রায়শই দেওয়া কারণ হিসাবে অস্পষ্ট "এটি সম্পাদনের জন্য" অস্পষ্টতার চেয়ে গিলতে একটি সহজ বড়ি।


13
এখানে আরও ভাল ব্যাখ্যা: স্ট্যাকওভারফ্লো
গিলি

3
এই EINTR আনব্লকিংটি ইউনিক্স থেকে প্রাপ্ত সিস্টেমগুলিতে সমস্ত ব্লকিং সিস্টেম কলগুলির ক্ষেত্রে সত্য। এটি কার্নেল প্রচুর সহজ করেছে, তবে অ্যাপ্লিকেশন প্রোগ্রামাররা বোঝাটি কিনে নিয়েছে।
টিম উইলিসক্রফ্ট

2
আমি ভেবেছিলাম pthread_cond_wait () এবং বন্ধুরা EINTR ফিরতে পারছে না, তবে উদ্দীপনা জাগলে শূন্য ফিরে আসবে? থেকে: pubs.opengroup.org/onlinepubs/7908799/xsh/… "এই ফাংশনগুলি [EINTR] এর ত্রুটি কোড ফেরত দেবে না।"
গুবি

2
@jgubby ঠিক আছে অন্তর্নিহিত futex()কলটি রিটার্ন দেয় EINTRতবে সেই রিটার্ন মানটি পরবর্তী স্তর পর্যন্ত বুবল হয় না। তাই পাইথ্রেড কলকারীকে অবশ্যই একজন আগত ব্যক্তির জন্য পরীক্ষা করা উচিত। তারা যা বলছে তা হ'ল pthread_cond_wait()প্রত্যাবর্তনের সময় আপনাকে অবশ্যই আপনার লুপের অবস্থা (আক্রমণকারী) আবার পরীক্ষা করতে হবে, কারণ অপেক্ষাটি তাত্ক্ষণিকভাবে জেগে ওঠে। সিস্টেম কল চলাকালীন সংকেত প্রাপ্তি একটি সম্ভাব্য কারণ, তবে এটি কেবল একমাত্র নয়।
জন কুগেলম্যান

1
সম্ভবত, pthreadগ্রন্থাগারটি তার নিজস্ব আক্রমণকারী এবং তার নিজস্ব চেকিং যুক্তি সরবরাহ করতে পারে যাতে ব্যবহারকারীর উপর সেই দায়বদ্ধতাটি উত্তোলন না করে উত্সাহী জাগরণগুলি দূর করতে পারে। এতে (সম্ভবত) দাবি করা পারফরম্যান্সের প্রভাব পড়বে।

22

আমার একটি উত্পাদন ব্যবস্থা রয়েছে যা এই আচরণটি প্রদর্শন করে। একটি থ্রেড একটি সংকেত অপেক্ষা করে যে কাতারে একটি বার্তা রয়েছে। ব্যস্ত সময়ে, 20% পর্যন্ত জাগ্রত উত্সাহিত হয় (যেমন এটি যখন জেগে থাকে তখন সারিতে কিছুই নেই)। এই থ্রেডটি বার্তাগুলির একমাত্র গ্রাহক। এটি একটি লিনাক্স এসইএলইএস -10 8-প্রসেসর বাক্সে চলে এবং এটি জিসিসি 4.1.2 দিয়ে নির্মিত। বার্তাগুলি একটি বাহ্যিক উত্স থেকে আসে এবং অবিচ্ছিন্নভাবে প্রক্রিয়া করা হয় কারণ সমস্যা আছে যদি আমার সিস্টেম সেগুলি তাড়াতাড়ি না পড়ায়।


15

শিরোনামে প্রশ্নের উত্তর দিতে - হ্যাঁ! এটি ঘটে যায় hযদি উইকি প্রবন্ধে জালিয়াতি জাগানো সম্পর্কে খুব ভাল আলোচনা করা হয়েছে তার জন্য একটি সুন্দর ব্যাখ্যা আমি পেয়েছি যা নীচে রয়েছে -

কেবল এটিকে ভাবুন ... যে কোনও কোডের মতো, থ্রেড শিডিয়ুলার অন্তর্নিহিত হার্ডওয়্যার / সফ্টওয়্যারটিতে অস্বাভাবিক কিছু ঘটার কারণে অস্থায়ী ব্ল্যাকআউট অনুভব করতে পারে। অবশ্যই এটি যথাসম্ভব বিরল হওয়ার জন্য যত্ন নেওয়া উচিত, তবে যেহেতু 100% মজবুত সফ্টওয়্যার বলে কিছু নেই তাই এটি ঘটতে পারে বলে ধরে নেওয়া যুক্তিসঙ্গত এবং যদি শিডিয়ুলার এটি সনাক্ত করে তবে ক্ষেত্রে সুদৃ recovery় পুনরুদ্ধারের যত্ন নেওয়া উচিত eg অনুপস্থিত হার্টবিট পর্যবেক্ষণ করে)।

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

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

আমি উত্স থেকে এই উত্তরটি পড়ছিলাম এবং এটি যথেষ্ট যুক্তিসঙ্গত বলে মনে করি। পড়াও

জাভাতে উত্সাহী জাগরণ এবং সেগুলি কীভাবে এড়ানো যায়

পিএস: উপরের লিঙ্কটি আমার ব্যক্তিগত ব্লগে এটিতে উত্সাহী জাগরণের বিষয়ে অতিরিক্ত বিশদ রয়েছে।


9

ক্যামেরুন পুরী একটি ব্লগ পোস্ট লিখেছিলেন কিছুক্ষণ আগে জালিয়াতিযুক্ত জাগ্রত সমস্যার কারণে আঘাত হানার কথা। হ্যাঁ, এটি ঘটে

আমি কিছুটা প্ল্যাটফর্মের সীমাবদ্ধতার কারণে যা জাভা মোতায়েন করা হয়েছে তা অনুমানের মধ্যে রেখেছি (সম্ভাবনা হিসাবে)? যদিও আমি ভুল হতে পারি!


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

এটি এসও-তে অন্য একটি প্রশ্ন: "এমন কোনও কঠোর ভিএম রয়েছে যা পরীক্ষার জন্য ব্যবহার করা যেতে পারে?" আমি কঠোর থ্রেড-লোকাল মেমোরি সহ একটি দেখতে পছন্দ করব - আমি মনে করি না তারা এখনও বিদ্যমান
অক্সবো_লাক

8

এই যোগ করতে। হ্যাঁ এটি ঘটে এবং আমি একটি 24 কোর মেশিনে (জেডিকে 6) একাধিক-থ্রেডিং সমস্যার কারণ অনুসন্ধানে তিন দিন ব্যয় করেছি। 10 এর মধ্যে 4 মৃত্যুদণ্ড কার্যকর হয়েছে যে কোনও বিন্যাস ছাড়াই। এটি 2 কোর বা 8 কোরে কখনও ঘটেনি।

কিছু অনলাইন উপাদান অধ্যয়ন করেছেন এবং এটি জাভা সমস্যা নয় তবে একটি সাধারণ বিরল তবে প্রত্যাশিত আচরণ।


হ্যালো রেনেস, আপনি কি সেখানে চলমান অ্যাপটি বিকাশ করছেন? বাহ্যিক অবস্থার লুপ চেক করার সময় এটি কী (অপেক্ষা) পদ্ধতিতে কল করার জন্য অপেক্ষা করেছিল (যা) জাভা ডক ডকস.অরাকল . com/ জাভ্যাস / / / ডকস / এপি / জাভা / লং / তে পরামর্শ দেওয়া হয়েছে ?
gumkins

আমি এটি সম্পর্কে লিখেছিলাম এবং হ্যাঁ সমাধানটি একটি শর্ত পরীক্ষা সহ কিছুক্ষণ লুপ। আমার ভুলটি ছিল নিখোঁজ লুপ ... তবে তাই আমি এই জাগ্রত সম্পর্কে শিখেছি ... দু'কোরে কখনও হয় না, প্রায়শই ২৪ স্কোর ব্লগ.অসেপ্টেন্স
২০১/0

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

0

অন্তর্নিহিত অপারেটিং সিস্টেমটি ট্রিগার না করলেও https://stackoverflow.com/a/1461956/14731 এ আপনাকে কেন জাঁকজমকপূর্ণ জাগানো বিরুদ্ধে রক্ষা করতে হবে তার একটি দুর্দান্ত ব্যাখ্যা রয়েছে। এটি আকর্ষণীয় বিষয় যে এই ব্যাখ্যাটি জাভা সহ একাধিক প্রোগ্রামিং ভাষাতে প্রযোজ্য।


0

ওপির প্রশ্নের জবাব দেওয়া

এলোমেলোভাবে কোনও ঘটনার জন্য চিরকালের জন্য অপেক্ষা না করে এই প্রত্যাশা জাগাতে আমি কী করতে পারি?

, কোনও উত্সাহী জাগরণ নেই এই অপেক্ষার থ্রেড জাগাতে পারে না!

কিনা কৃত্রিম wakeups বা ওপি একটি ক্ষেত্রে একটি নির্দিষ্ট প্ল্যাটফর্মে ঘটবে না পারে, তথাপি এর snippet ইতিবাচক হয় অসম্ভব জন্যCondition.await() ফিরে যাওয়ার এবং লাইন দেখার জন্য "কৃত্রিম ওয়েকআপ!" আউটপুট প্রবাহে।

আপনি যদি না খুব বিদেশী জাভা ক্লাস লাইব্রেরি ব্যবহার করছেন

এর কারণ হল মান হল OpenJDK এর ReentrantLock'র পদ্ধতি newCondition()আয় AbstractQueuedSynchronizer' এর গুলি বাস্তবায়ন Conditionইন্টারফেস, নেস্টেড ConditionObject(উপায় দ্বারা, এটি একমাত্র বাস্তবায়ন Conditionএই শ্রেণীর লাইব্রেরিতে ইন্টারফেস), এবং ConditionObjectএর পদ্ধতিawait() নিজেই কিনা তা পরীক্ষা শর্ত না ধারণ করে এবং কোনও উত্সাহী জাগ্রত এই পদ্ধতিটি ভুল করে ফিরে আসতে বাধ্য করতে পারে না।

যাইহোক, আপনি নিজে এটি পরীক্ষা করতে পারেন কারণ একবার AbstractQueuedSynchronizerভিত্তিযুক্ত বাস্তবায়ন জড়িত থাকার পরে উত্সাহী জাগরণ অনুকরণ করা বেশ সহজ । AbstractQueuedSynchronizerনিম্ন স্তরের ব্যবহার LockSupportএর parkএবং unparkপদ্ধতি, এবং যদি আপনি ডাকা LockSupport.unparkএকটি থ্রেডে অপেক্ষা উপর Condition, এই ক্রিয়াটির একটি কৃত্রিম ওয়েকআপ থেকে আলাদা করা যাবে না।

ওপির স্নিপেটটি সামান্যভাবে রিফ্যাক্টরিং,

public class Spurious {

    private static class AwaitingThread extends Thread {

        @Override
        public void run() {
            Lock lock = new ReentrantLock();
            Condition cond = lock.newCondition();
            lock.lock();
            try {
                try {
                    cond.await();
                    System.out.println("Spurious wakeup!");
                } catch (InterruptedException ex) {
                    System.out.println("Just a regular interrupt.");
                }
            } finally {
                lock.unlock();
            }
        }
    }

    private static final int AMOUNT_OF_SPURIOUS_WAKEUPS = 10;

    public static void main(String[] args) throws InterruptedException {
        Thread awaitingThread = new AwaitingThread();
        awaitingThread.start();
        Thread.sleep(10000);
        for(int i =0 ; i < AMOUNT_OF_SPURIOUS_WAKEUPS; i++)
            LockSupport.unpark(awaitingThread);
        Thread.sleep(10000);
        if (awaitingThread.isAlive())
            System.out.println("Even after " + AMOUNT_OF_SPURIOUS_WAKEUPS + " \"spurious wakeups\" the Condition is stil awaiting");
        else
            System.out.println("You are using very unusual implementation of java.util.concurrent.locks.Condition");
    }
}

, এবং আনপার্কিং (মূল) থ্রেডটি অপেক্ষমান থ্রেডটি জাগ্রত করার চেষ্টা করুক না কেন, Condition.await()পদ্ধতিটি এই ক্ষেত্রে আর ফিরে আসবে না।

উপর কৃত্রিম wakeups Conditionএর অপেক্ষা পদ্ধতি আলোচনা করা হয়েছে এর javadoc Conditionইন্টারফেস । যদিও এটি বলে যে,

যখন কোনও শর্তের অপেক্ষায়, একটি উত্সাহী জাগ্রত হওয়ার অনুমতি দেওয়া হয়

এবং সেটা

এটি প্রস্তাবিত হয় যে অ্যাপ্লিকেশন প্রোগ্রামাররা সবসময় ধরে নেয় যে তারা ঘটতে পারে এবং তাই সর্বদা একটি লুপে অপেক্ষা করুন।

তবে এটি পরে যুক্ত করে

উদ্দীপনা জাগ্রত হওয়ার সম্ভাবনা অপসারণের জন্য একটি বাস্তবায়ন নিখরচায়

এবং ইন্টারফেসের AbstractQueuedSynchronizerবাস্তবায়ন Conditionঠিক তা করে - উত্সাহী জাগরণের কোনও সম্ভাবনা সরিয়ে দেয়

এটি অবশ্যই অন্যের জন্য সত্যকে ধারণ করে ConditionObject অপেক্ষার পদ্ধতির ক্ষেত্রে ।

তাহলে উপসংহারটি হল:

আমাদের সর্বদা Condition.awaitলুপে কল করা উচিত এবং শর্তটি ধরে রাখে না কিনা তা খতিয়ে দেখা উচিত, তবে স্ট্যান্ডার্ড, ওপেনজেডিকে, জাভা ক্লাস লাইব্রেরিটি কখনই ঘটতে পারে না । যদি না আবার আপনি খুব অসাধারণ জাভা ক্লাস লাইব্রেরি ব্যবহার করেন (যা অবশ্যই খুব অস্বাভাবিক হতে হবে, কারণ অন্য একটি সুপরিচিত নন-ওপেনজেডি কে জাভা ক্লাস লাইব্রেরিগুলি, বর্তমানে প্রায় বিলুপ্ত জিএনইউ ক্লাসপাথ এবং অ্যাপাচি হারমোনিগুলিকেCondition ইন্টারফেসের স্ট্যান্ডার্ড বাস্তবায়নের অনুরূপ বলে মনে হচ্ছে )

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