C ++ 0x में कोई अर्धवृत्त नहीं है? धागे को कैसे सिंक्रनाइज़ करें?


135

क्या यह सच है कि C ++ 0x बिना सेमाफोर के आएगा? सेमीफोर के उपयोग के संबंध में स्टैक ओवरफ्लो पर पहले से ही कुछ प्रश्न हैं। मैं उन्हें (पॉज़िक्स सेमाफ़ोर्स) हर समय एक धागे को किसी दूसरे सूत्र में किसी घटना की प्रतीक्षा करने के लिए उपयोग करता हूँ:

void thread0(...)
{
  doSomething0();

  event1.wait();

  ...
}

void thread1(...)
{
  doSomething1();

  event1.post();

  ...
}

अगर मैं म्यूटेक्स के साथ ऐसा करूंगा:

void thread0(...)
{
  doSomething0();

  event1.lock(); event1.unlock();

  ...
}

void thread1(...)
{
  event1.lock();

  doSomethingth1();

  event1.unlock();

  ...
}

समस्या: यह बदसूरत है और यह गारंटी नहीं है कि थ्रेड 1 पहले म्यूटेक्स को लॉक करता है (यह देखते हुए कि एक ही थ्रेड लॉक होना चाहिए और म्यूटेक्स को अनलॉक करना चाहिए, आप थ्रेड 1 और थ्रेड 1 शुरू होने से पहले ईवेंट 1 को लॉक नहीं कर सकते हैं)।

इसलिए चूंकि बूस्ट में सेमाफोर भी नहीं है, इसलिए उपरोक्त प्राप्त करने का सबसे सरल तरीका क्या है?


शायद हालत mutex और एसटीडी का उपयोग करें :: वादा और एसटी :: भविष्य?
यवेस

जवाबों:


179

आप आसानी से एक म्यूटेक्स और एक स्थिति चर से निर्माण कर सकते हैं:

#include <mutex>
#include <condition_variable>

class semaphore
{
private:
    std::mutex mutex_;
    std::condition_variable condition_;
    unsigned long count_ = 0; // Initialized as locked.

public:
    void notify() {
        std::lock_guard<decltype(mutex_)> lock(mutex_);
        ++count_;
        condition_.notify_one();
    }

    void wait() {
        std::unique_lock<decltype(mutex_)> lock(mutex_);
        while(!count_) // Handle spurious wake-ups.
            condition_.wait(lock);
        --count_;
    }

    bool try_wait() {
        std::lock_guard<decltype(mutex_)> lock(mutex_);
        if(count_) {
            --count_;
            return true;
        }
        return false;
    }
};

96
किसी को मानकों का प्रस्ताव प्रस्तुत करना चाहिए

7
यहां एक टिप्पणी जिसने मुझे शुरुआत में हैरान कर दिया था, वह है वेट इन लॉक, कोई यह पूछ सकता है कि अगर थ्रेड को प्रतीक्षा के दौरान होल्ड किया जाता है तो थ्रेड को कैसे सूचित किया जा सकता है? कुछ हद तक अस्पष्ट अस्पष्ट रूप से प्रलेखित उत्तर यह है कि condition_variable.wait लॉक को दाल देता है, जिससे एक और धागा परमाणु ऊर्जा में अतीत को सूचित कर सकता है, कम से कम यह है कि मैं इसे कैसे समझता हूं

31
यह बूस्ट से जानबूझकर इस आधार पर बाहर रखा गया था कि प्रोग्रामरों के लिए एक सेमाफोर बहुत अधिक रस्सी है ताकि वे खुद को लटका सकें। माना जाता है कि हालत चर अधिक प्रबंधनीय हैं। मैं उनकी बात देख रहा हूं लेकिन थोड़ा सा संरक्षण महसूस करता हूं। मेरा मानना ​​है कि यही तर्क C ++ 11 पर लागू होता है - प्रोग्रामर से अपेक्षा की जाती है कि वे अपने कार्यक्रमों को इस तरह से लिखें कि "स्वाभाविक रूप से" कंडेंसर या अन्य स्वीकृत सिंक्रोनाइज़ेशन तकनीकों का उपयोग करें। आपूर्ति एक सेमाफोर के खिलाफ चलेगी चाहे वह कंडेवर के शीर्ष पर लागू हो या मूल रूप से।
स्टीव जेसोप

5
नोट - लूप के पीछे तर्क के लिए en.wikipedia.org/wiki/Spurious_wakeup देखें while(!count_)
डैन निसेनबूम

3
@ मोम मुझे माफ करना, मुझे नहीं लगता कि तुम सही हो। sem_wait और sem_post केवल विवाद पर ही syscall भी (check sourceware.org/git/?p=glibc.git/a=blob;f=nptl/sem_wait.c ) ताकि कोड्स का अंत हो जाता है, जो कि फेक इंप्लीमेंटेशन को कार्यान्वित करता है, संभावित बग्स के साथ। यदि आप किसी भी सिस्टम पर पोर्टेबिलिटी का इरादा रखते हैं, तो यह एक समाधान हो सकता है, लेकिन यदि आपको केवल पॉसिक्स संगतता की आवश्यकता है, तो पॉज़िक्स सेमाफोर का उपयोग करें।
xryl669

107

मैक्सिम येगोरुस्किन के जवाब के आधार पर , मैंने C ++ 11 शैली में उदाहरण बनाने की कोशिश की।

#include <mutex>
#include <condition_variable>

class Semaphore {
public:
    Semaphore (int count_ = 0)
        : count(count_) {}

    inline void notify()
    {
        std::unique_lock<std::mutex> lock(mtx);
        count++;
        cv.notify_one();
    }

    inline void wait()
    {
        std::unique_lock<std::mutex> lock(mtx);

        while(count == 0){
            cv.wait(lock);
        }
        count--;
    }

private:
    std::mutex mtx;
    std::condition_variable cv;
    int count;
};

34
आप इंतजार कर सकते हैं () भी एक तीन-लाइनर:cv.wait(lck, [this]() { return count > 0; });
डॉमी

2
लॉक_गार्ड की भावना में एक और वर्ग जोड़ना सहायक है, भी। RAII फैशन में, कंस्ट्रक्टर, जो सेमाफोर को एक संदर्भ के रूप में लेता है, सेमाफोर के वेट () कॉल को बुलाता है, और विध्वंसक अपने नोटिफ़िकेशन () कॉल को कॉल करता है। यह सेमाफ़ोर को जारी करने में विफल होने से अपवादों को रोकता है।
जिम हन्ज़िकर

क्या कोई डेड-लॉक नहीं है, अगर एन थ्रेड्स को प्रतीक्षा कहा जाता है () और गिनती == 0, तो cv.notify_one (); कभी नहीं कहा जाता है, क्योंकि mtx जारी नहीं किया है?
मार्सेलो

1
@ मार्सेललो प्रतीक्षा सूत्र लॉक को पकड़ नहीं पाता है। हालत चर का पूरा बिंदु एक परमाणु "अनलॉक और प्रतीक्षा" ऑपरेशन प्रदान करना है।
डेविड श्वार्ट्ज

3
आपको कॉल करने से पहले लॉक जारी करना चाहिए Inform_one () तुरंत वॉकअप से बचने के लिए ... यहाँ देखें: en.cppreference.com/w/cpp/thread/condition_variable/notify_all
kylefinn

38

मैंने सबसे मजबूत / जेनेरिक C ++ 11 सेमीफोर को लिखने का फैसला किया, जो मानक की शैली में मैं जितना कर सकता था (ध्यान दें using semaphore = ..., आप आमतौर पर सिर्फ semaphoreसामान्य रूप से उपयोग stringनहीं होने वाले नाम का उपयोग करेंगे basic_string):

template <typename Mutex, typename CondVar>
class basic_semaphore {
public:
    using native_handle_type = typename CondVar::native_handle_type;

    explicit basic_semaphore(size_t count = 0);
    basic_semaphore(const basic_semaphore&) = delete;
    basic_semaphore(basic_semaphore&&) = delete;
    basic_semaphore& operator=(const basic_semaphore&) = delete;
    basic_semaphore& operator=(basic_semaphore&&) = delete;

    void notify();
    void wait();
    bool try_wait();
    template<class Rep, class Period>
    bool wait_for(const std::chrono::duration<Rep, Period>& d);
    template<class Clock, class Duration>
    bool wait_until(const std::chrono::time_point<Clock, Duration>& t);

    native_handle_type native_handle();

private:
    Mutex   mMutex;
    CondVar mCv;
    size_t  mCount;
};

using semaphore = basic_semaphore<std::mutex, std::condition_variable>;

template <typename Mutex, typename CondVar>
basic_semaphore<Mutex, CondVar>::basic_semaphore(size_t count)
    : mCount{count}
{}

template <typename Mutex, typename CondVar>
void basic_semaphore<Mutex, CondVar>::notify() {
    std::lock_guard<Mutex> lock{mMutex};
    ++mCount;
    mCv.notify_one();
}

template <typename Mutex, typename CondVar>
void basic_semaphore<Mutex, CondVar>::wait() {
    std::unique_lock<Mutex> lock{mMutex};
    mCv.wait(lock, [&]{ return mCount > 0; });
    --mCount;
}

template <typename Mutex, typename CondVar>
bool basic_semaphore<Mutex, CondVar>::try_wait() {
    std::lock_guard<Mutex> lock{mMutex};

    if (mCount > 0) {
        --mCount;
        return true;
    }

    return false;
}

template <typename Mutex, typename CondVar>
template<class Rep, class Period>
bool basic_semaphore<Mutex, CondVar>::wait_for(const std::chrono::duration<Rep, Period>& d) {
    std::unique_lock<Mutex> lock{mMutex};
    auto finished = mCv.wait_for(lock, d, [&]{ return mCount > 0; });

    if (finished)
        --mCount;

    return finished;
}

template <typename Mutex, typename CondVar>
template<class Clock, class Duration>
bool basic_semaphore<Mutex, CondVar>::wait_until(const std::chrono::time_point<Clock, Duration>& t) {
    std::unique_lock<Mutex> lock{mMutex};
    auto finished = mCv.wait_until(lock, t, [&]{ return mCount > 0; });

    if (finished)
        --mCount;

    return finished;
}

template <typename Mutex, typename CondVar>
typename basic_semaphore<Mutex, CondVar>::native_handle_type basic_semaphore<Mutex, CondVar>::native_handle() {
    return mCv.native_handle();
}

यह एक छोटे से संपादन के साथ काम करता है। wait_forऔर wait_untilविधेय के साथ विधि कॉल एक बूलियन मान (नहीं एक `std :: cv_status) लौट आते हैं।
jdknight

खेल में इतनी देर से नाइट-पिक करने के लिए क्षमा करें। std::size_tयह अहस्ताक्षरित है इसलिए इसे शून्य से नीचे घटाना यूबी है, और यह हमेशा रहेगा >= 0। IMHO countहोना चाहिए int
रिचर्ड होजेस

3
@RichardHodges शून्य से कम होने का कोई रास्ता नहीं है इसलिए कोई समस्या नहीं है, और एक अर्धवृत्त पर एक नकारात्मक गणना क्या होगी? यह भी मतलब नहीं है IMO।
डेविड

1
@ डेविड अगर किसी थ्रेड को अन्य चीजों के लिए इंतजार करना पड़े तो क्या होगा? उदाहरण के लिए, 1 पाठक धागा 4 थ्रेड्स के लिए प्रतीक्षा करने के लिए, मैं -3 के साथ सेमाफोर कंस्ट्रक्टर को कॉल करूंगा ताकि पाठक थ्रेड इंतजार न कर सके अन्य सभी थ्रेड्स ने एक पोस्ट किया। मुझे लगता है कि ऐसा करने के अन्य तरीके हैं, लेकिन क्या यह उचित नहीं है? मुझे लगता है कि यह वास्तव में सवाल है जो ओपी पूछ रहा है लेकिन अधिक "थ्रेड 1" के साथ।
जम्मु

2
@RichardHodges बहुत पांडित्यपूर्ण है, 0 से नीचे एक अहस्ताक्षरित पूर्णांक प्रकार घटाना UB नहीं है।
jcai

15

posix semaphores के साथ एकॉर्ड में, मैं जोड़ूंगा

class semaphore
{
    ...
    bool trywait()
    {
        boost::mutex::scoped_lock lock(mutex_);
        if(count_)
        {
            --count_;
            return true;
        }
        else
        {
            return false;
        }
    }
};

और मैं एब्स्ट्रैक्शन के सुविधाजनक स्तर पर सिंक्रोनाइज़ेशन मैकेनिज्म का उपयोग करना ज्यादा पसंद करता हूं, बजाय इसके कि अधिक मूल संचालकों का उपयोग करके सिले-सिलाए गए संस्करण को हमेशा चिपकाएँ।


9

आप cpp11-on-multicore की भी जांच कर सकते हैं - इसमें एक पोर्टेबल और इष्टतम सेमाफोर कार्यान्वयन है।

रिपॉजिटरी में अन्य थ्रेडिंग गुड भी होते हैं जो c ++ 11 थ्रेडिंग के पूरक हैं।


8

आप म्यूटेक्स और कंडीशन वेरिएबल्स के साथ काम कर सकते हैं। आप म्यूटेक्स के साथ अनन्य पहुंच प्राप्त करते हैं, जांचें कि क्या आप जारी रखना चाहते हैं या दूसरे छोर तक इंतजार करना चाहते हैं। यदि आपको प्रतीक्षा करने की आवश्यकता है, तो आप एक स्थिति में प्रतीक्षा करते हैं। जब दूसरा धागा निर्धारित करता है कि आप जारी रख सकते हैं, तो यह स्थिति को इंगित करता है।

बढ़ावा देने में एक छोटा उदाहरण है :: थ्रेड लाइब्रेरी जिसे आप शायद केवल कॉपी कर सकते हैं (C ++ 0x और बूस्ट थ्रेड लिबास बहुत समान हैं)।


सिर्फ़ वेटिंग थ्रेड्स के लिए कंडीशन के संकेत, या नहीं? इसलिए अगर थ्रेड 1 सिग्नल के बाद थ्रेड0 इंतज़ार नहीं कर रहा है तो इसे बाद में ब्लॉक कर दिया जाएगा? प्लस: मुझे अतिरिक्त लॉक की आवश्यकता नहीं है जो शर्त के साथ आता है - यह ओवरहेड है।
वृषभान

हां, हालत केवल इंतजार कर रहे धागे का संकेत देती है। सामान्य पैटर्न राज्य के साथ एक चर है और यदि आपको प्रतीक्षा करने की आवश्यकता है तो एक शर्त। निर्माता / उपभोक्ता पर विचार करें, बफर में वस्तुओं पर एक गिनती होगी, निर्माता ताले लगाता है, तत्व जोड़ता है, गिनती और संकेतों को बढ़ाता है। उपभोक्ता लॉक करता है, काउंटर की जांच करता है और यदि गैर-शून्य खपत करता है, जबकि शून्य स्थिति में प्रतीक्षा करता है।
डेविड रॉड्रिग्ज -

2
आप इस तरह से एक सेमाफोर का अनुकरण कर सकते हैं: मान के साथ एक वैरिएबल की शुरुआत करें, जिसे आप सेमाफोर देंगे, फिर wait()"लॉक की जांच करें, यदि गैर-शून्य विकृति और जारी रहती है, तो गिनती की जांच करें"; शून्य postहोगा जब स्थिति "लॉक" होगी। वृद्धि काउंटर, संकेत अगर यह 0 था
डेविड रॉड्रिग्ज -

हां, सुनने में तो अच्छा है। मुझे आश्चर्य है कि अगर पॉज़िक्स सेमाफोर को उसी तरह लागू किया जाता है।
वृषभ

@tauran: मैं निश्चित रूप से नहीं जानता (और यह निर्भर करता है कि कौन सा Posix OS हो), लेकिन मुझे लगता है कि संभावना नहीं है। पारंपरिक रूप से म्यूटेक्स और कंडीशन वैरिएबल की तुलना में सेमाफोर एक "लो-लेवल" सिंक्रोनाइजेशन प्राइमेटिव हैं, और अगर कंडोवर के ऊपर इसे लागू किया जाता है, तो सिद्धांत रूप में उन्हें अधिक कुशल बनाया जा सकता है। इसलिए, किसी दिए गए OS में अधिक संभावना यह है कि सभी उपयोगकर्ता-स्तरीय सिंक प्राइमेटिव कुछ सामान्य टूल के ऊपर बनाए गए हैं जो शेड्यूलर के साथ बातचीत करते हैं।
स्टीव जेसोप

3

धागे में उपयोगी RAII अर्ध-आवरण भी हो सकता है:

class ScopedSemaphore
{
public:
    explicit ScopedSemaphore(Semaphore& sem) : m_Semaphore(sem) { m_Semaphore.Wait(); }
    ScopedSemaphore(const ScopedSemaphore&) = delete;
    ~ScopedSemaphore() { m_Semaphore.Notify(); }

   ScopedSemaphore& operator=(const ScopedSemaphore&) = delete;

private:
    Semaphore& m_Semaphore;
};

मल्टीथ्रेड एप्लिकेशन में उपयोग उदाहरण:

boost::ptr_vector<std::thread> threads;
Semaphore semaphore;

for (...)
{
    ...
    auto t = new std::thread([..., &semaphore]
    {
        ScopedSemaphore scopedSemaphore(semaphore);
        ...
    }
    );
    threads.push_back(t);
}

for (auto& t : threads)
    t.join();

3

C ++ 20 में अंत में सेमीफ़ोर्स होगा - std::counting_semaphore<max_count>

इनमें निम्न विधियाँ होंगी (कम से कम):

  • acquire() (ब्लॉकिंग)
  • try_acquire() (नॉन-ब्लॉकिंग, रिटर्न तत्काल)
  • try_acquire_for() (गैर-अवरुद्ध, एक अवधि लेता है)
  • try_acquire_until() (नॉन-ब्लॉकिंग, एक समय लगता है जिस पर कोशिश करना बंद कर दें)
  • release()

यह अभी तक cppreference पर सूचीबद्ध नहीं है, लेकिन आप इन CppCon 2019 प्रस्तुति स्लाइड्स को पढ़ सकते हैं , या वीडियो देख सकते हैं । P0514R4 का आधिकारिक प्रस्ताव भी है , लेकिन मुझे यकीन नहीं है कि यह सबसे अद्यतित संस्करण है।


2

मुझे एक सूची के साथ साझा किया गया, जो कि मुझे आवश्यक था, ने साझा किया। मेरा मुद्दा था, मेरे पास कई ग्राहक थे जो एक होस्ट के आंतरिक डेटा के साथ बातचीत करना चाहते थे। आमतौर पर, होस्ट डेटा को स्वयं अपडेट करता है, हालांकि, यदि कोई क्लाइंट इसे अनुरोध करता है, तो होस्ट को तब तक अपडेट करने से रोकने की आवश्यकता है जब तक कोई क्लाइंट होस्ट डेटा तक नहीं पहुंच रहा हो। उसी समय, कोई ग्राहक अनन्य एक्सेस के लिए कह सकता है, ताकि कोई अन्य क्लाइंट, और न ही होस्ट, उस होस्ट डेटा को संशोधित कर सके।

मैंने यह कैसे किया, मैंने एक संरचना बनाई:

struct UpdateLock
{
    typedef std::shared_ptr< UpdateLock > ptr;
};

प्रत्येक ग्राहक ऐसा होगा:

UpdateLock::ptr m_myLock;

तब मेजबान में विशिष्टता के लिए एक कमजोर_प्रति सदस्य और गैर-अनन्य ताले के लिए कमजोर_पत्रों की एक सूची होगी:

std::weak_ptr< UpdateLock > m_exclusiveLock;
std::list< std::weak_ptr< UpdateLock > > m_locks;

लॉक करने में सक्षम करने के लिए एक फ़ंक्शन है, और होस्ट लॉक है या नहीं यह जांचने के लिए एक और फ़ंक्शन है:

UpdateLock::ptr LockUpdate( bool exclusive );       
bool IsUpdateLocked( bool exclusive ) const;

मैं LockUpdate, IsUpdateLocked, और समय-समय पर होस्ट की अद्यतन दिनचर्या में ताले के लिए परीक्षण करता हूं। लॉक के लिए परीक्षण करना उतना ही सरल है, जितना कि कमजोर_प्रति की समय सीमा समाप्त होने पर और m_locks सूची से कोई भी समय सीमा समाप्त करने की जाँच करना (मैं केवल होस्ट अपडेट के दौरान ऐसा करता हूं), मैं जांच कर सकता हूं कि क्या सूची खाली है; उसी समय, मुझे स्वचालित अनलॉकिंग मिलती है जब एक ग्राहक साझा किए गए शेयर को साझा करता है। वे उस पर लटके होते हैं, जो तब भी होता है जब एक ग्राहक स्वचालित रूप से नष्ट हो जाता है।

सभी प्रभाव पर, क्योंकि ग्राहकों को शायद ही कभी विशिष्टता की आवश्यकता होती है (आम तौर पर केवल परिवर्धन और विलोपन के लिए आरक्षित होती है), ज्यादातर समय लॉकअपडेट (गलत) के लिए एक अनुरोध, जिसे गैर-अनन्य कहना है, तब तक सफल होता है जब तक (! M_exclusiveLock)। और एक लॉकअपडेट (सच्चा), विशिष्टता के लिए एक अनुरोध, तभी सफल होता है जब दोनों (! M_exclusiveLock) और (m_locks.empty ())।

अनन्य और गैर-अनन्य ताले के बीच शमन करने के लिए एक कतार को जोड़ा जा सकता है, हालांकि, मेरे पास अब तक कोई टक्कर नहीं है, इसलिए मैं इंतजार करता हूं कि जब तक समाधान जोड़ने के लिए नहीं होता है (ज्यादातर तो मेरे पास एक वास्तविक दुनिया परीक्षण स्थिति है)।

अब तक यह मेरी जरूरतों के लिए अच्छा काम कर रहा है; मैं इसे विस्तारित करने की आवश्यकता की कल्पना कर सकता हूं, और कुछ मुद्दे जो विस्तारित उपयोग पर उत्पन्न हो सकते हैं, हालांकि, इसे लागू करने के लिए त्वरित था, और बहुत कम कस्टम कोड की आवश्यकता थी।


-4

यदि कोई परमाणु संस्करण में रुचि रखता है, तो यहां कार्यान्वयन है। प्रदर्शन म्यूटेक्स और स्थिति चर संस्करण से बेहतर होने की उम्मीद है।

class semaphore_atomic
{
public:
    void notify() {
        count_.fetch_add(1, std::memory_order_release);
    }

    void wait() {
        while (true) {
            int count = count_.load(std::memory_order_relaxed);
            if (count > 0) {
                if (count_.compare_exchange_weak(count, count-1, std::memory_order_acq_rel, std::memory_order_relaxed)) {
                    break;
                }
            }
        }
    }

    bool try_wait() {
        int count = count_.load(std::memory_order_relaxed);
        if (count > 0) {
            if (count_.compare_exchange_strong(count, count-1, std::memory_order_acq_rel, std::memory_order_relaxed)) {
                return true;
            }
        }
        return false;
    }
private:
    std::atomic_int count_{0};
};

4
मैं प्रदर्शन के बहुत खराब होने की उम्मीद करूंगा । यह कोड लगभग हर संभव गलती करता है। सबसे स्पष्ट उदाहरण के रूप में, मान लीजिए कि waitकोड को कई बार लूप करना पड़ता है। जब यह अंत में अनब्लॉक होता है, तो यह सभी गलत शाखाओं की माँ को ले जाएगा क्योंकि सीपीयू की लूप भविष्यवाणी निश्चित रूप से भविष्यवाणी करेगी कि यह फिर से लूप करेगी। मैं इस कोड के साथ कई और मुद्दों को सूचीबद्ध कर सकता हूं।
डेविड श्वार्ट्ज

1
यहां एक और स्पष्ट प्रदर्शन हत्यारा है: waitलूप सीपीयू माइक्रोएक्सेशन संसाधनों का उपभोग करेगा क्योंकि यह घूमता है। मान लीजिए कि यह उसी भौतिक कोर में है, जिस धागे को माना जाता है notify- यह उस धागे को बहुत धीमा कर देगा।
डेविड श्वार्ट्ज

1
और यहाँ सिर्फ एक और है: x86 सीपीयू (सबसे लोकप्रिय सीपीयू आज) पर, एक Compar_exchange_weak ऑपरेशन हमेशा एक लेखन ऑपरेशन होता है, भले ही वह विफल हो (यह वही मूल्य वापस लिखता है जो अगर तुलना में विफल रहता है)। तो मान लीजिए कि एक waitही सेमीफोर के लिए दो कोर एक लूप में हैं । वे दोनों पूरी गति से एक ही कैश लाइन पर लिख रहे हैं , जो अंतर-कोर बसों को संतृप्त करके एक कोर को अन्य क्रॉल को धीमा कर सकती हैं।
डेविड श्वार्ट्ज

@DavidSchwartz Glad आपकी टिप्पणियाँ देखने के लिए। यकीन नहीं होता कि '... सीपीयू का पाश भविष्यवाणी ...' भाग। दूसरे को सहमत किया। जाहिरा तौर पर आपका तीसरा मामला हो सकता है, लेकिन म्यूटेक्स की तुलना करें जो उपयोगकर्ता-मोड को कर्नेल-मोड स्विच और सिस्टम कॉल का कारण बनता है, इंटर-कोर सिंक बदतर नहीं है।
जेफरी

1
लॉक फ्री सेमाफोर जैसी कोई चीज नहीं है। लॉक फ्री होने का पूरा विचार म्यूटेक्स का उपयोग किए बिना कोड लिखना नहीं है, बल्कि कोड लिखना है जहां एक धागा कभी भी ब्लॉक नहीं होता है। इस मामले में सेमाफोर का सार उन धागों को अवरुद्ध करना है जो प्रतीक्षा () फ़ंक्शन को कहते हैं!
कार्लो वुड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.