लाइवलॉक का अच्छा उदाहरण?


141

मैं समझता हूं कि लाइवलॉक क्या है, लेकिन मैं सोच रहा था कि क्या किसी के पास इसका एक अच्छा कोड-आधारित उदाहरण था? और कोड-आधारित से मेरा मतलब यह नहीं है कि "दो लोग एक गलियारे में एक-दूसरे को पाने की कोशिश कर रहे हैं"। अगर मैंने फिर से पढ़ा, तो मैं अपना दोपहर का भोजन खो दूंगा।


96
कैसे एक गलियारे में एक दूसरे को पाने की कोशिश कर रहे दो लोगों के सॉफ़्टवेयर सिमुलेशन के बारे में?
1800 सूचना 5

36
तुम्हें श्राप लगे! मैंने अपना लंच खो दिया!
एलेक्स मिलर

3
विचित्र रूप से उपयुक्त: seuss.wikia.com/wiki/The_Zax
'15

जिज्ञासु फोलों के
01/

4
एक गलियारे में एक-दूसरे को पाने की कोशिश कर रहे दो लोग: gist.github.com/deepankarb/d2dd6f21bc49902376e614d3746b8965 : p
iceman

जवाबों:


119

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

public class Livelock {
    static class Spoon {
        private Diner owner;
        public Spoon(Diner d) { owner = d; }
        public Diner getOwner() { return owner; }
        public synchronized void setOwner(Diner d) { owner = d; }
        public synchronized void use() { 
            System.out.printf("%s has eaten!", owner.name); 
        }
    }

    static class Diner {
        private String name;
        private boolean isHungry;

        public Diner(String n) { name = n; isHungry = true; }       
        public String getName() { return name; }
        public boolean isHungry() { return isHungry; }

        public void eatWith(Spoon spoon, Diner spouse) {
            while (isHungry) {
                // Don't have the spoon, so wait patiently for spouse.
                if (spoon.owner != this) {
                    try { Thread.sleep(1); } 
                    catch(InterruptedException e) { continue; }
                    continue;
                }                       

                // If spouse is hungry, insist upon passing the spoon.
                if (spouse.isHungry()) {                    
                    System.out.printf(
                        "%s: You eat first my darling %s!%n", 
                        name, spouse.getName());
                    spoon.setOwner(spouse);
                    continue;
                }

                // Spouse wasn't hungry, so finally eat
                spoon.use();
                isHungry = false;               
                System.out.printf(
                    "%s: I am stuffed, my darling %s!%n", 
                    name, spouse.getName());                
                spoon.setOwner(spouse);
            }
        }
    }

    public static void main(String[] args) {
        final Diner husband = new Diner("Bob");
        final Diner wife = new Diner("Alice");

        final Spoon s = new Spoon(husband);

        new Thread(new Runnable() { 
            public void run() { husband.eatWith(s, wife); }   
        }).start();

        new Thread(new Runnable() { 
            public void run() { wife.eatWith(s, husband); } 
        }).start();
    }
}

6
getOwnerविधि के रूप में अच्छी तरह से सिंक्रनाइज़ करने के लिए नहीं है ? प्रभावी जावा से " सिंक्रनाइज़ेशन का तब तक कोई प्रभाव नहीं पड़ता जब तक कि दोनों पढ़े और न लिखे "।
सांग्युन ली

क्या उसे Thread.join()इसके बजाय उपयोग नहीं करना चाहिए Thread.sleep(), क्योंकि वह अपने भोजन करने के लिए पति की प्रतीक्षा करना चाहता है?
सोलेस

इस विशेष उदाहरण में लाइवलॉक की समस्या को दूर करने के लिए हमें क्या करना चाहिए?
थोर

1
getOwnerविधि सिंक्रनाइज़ किया जाना चाहिए के बाद से भले ही setOwnerसिंक्रनाइज़ है, इस का उपयोग करते हुए धागे की गारंटी नहीं है getOwner(या क्षेत्र तक पहुँचने ownerसीधे) अन्य धागा प्रदर्शन से किए गए परिवर्तनों को देखेंगे setOwner। यह vid इसे बहुत सावधानी से समझाता है: youtube.com/watch?v=WTVooKLLVT8
Timofey

2
आपको विधि के synchronized लिए कीवर्ड का उपयोग करने की आवश्यकता नहीं है setOwner, क्योंकि पढ़ना और लिखना संदर्भ चर के लिए परमाणु क्रिया है।
11:17 पर

75

अलग-अलग टिप्पणियों में, एक उदाहरण जो ऊपर आने के लिए जाना जाता है, कोड में है जो गतिरोध स्थितियों का पता लगाने और संभालने की कोशिश करता है। यदि दो सूत्र एक गतिरोध का पता लगाते हैं, और एक दूसरे के लिए "अलग हटकर" कदम उठाने की कोशिश करते हैं, तो बिना किसी परवाह के वे एक पाश में हमेशा "कदम अलग" करते हुए फंस जाएंगे और कभी भी आगे बढ़ने का प्रबंधन नहीं करेंगे।

"एक तरफ कदम" से मेरा मतलब है कि वे ताला छोड़ देंगे और दूसरे को इसे हासिल करने का प्रयास करेंगे। हम ऐसा करने वाले दो धागों के साथ स्थिति की कल्पना कर सकते हैं (छद्मकोश):

// thread 1
getLocks12(lock1, lock2)
{
  lock1.lock();
  while (lock2.locked())
  {
    // attempt to step aside for the other thread
    lock1.unlock();
    wait();
    lock1.lock();
  }
  lock2.lock();
}

// thread 2
getLocks21(lock1, lock2)
{
  lock2.lock();
  while (lock1.locked())
  {
    // attempt to step aside for the other thread
    lock2.unlock();
    wait();
    lock2.lock();
  }
  lock1.lock();
}

दौड़ की स्थिति एक तरफ, हमारे पास यहां एक ऐसी स्थिति है जहां दोनों धागे, अगर वे एक ही समय में प्रवेश करते हैं, तो आगे बढ़ने के बिना आंतरिक लूप में चलना समाप्त हो जाएगा। जाहिर है कि यह एक सरल उदाहरण है। धागे को इंतजार करने के समय की राशि में किसी प्रकार की यादृच्छिकता डालने के लिए एक निश्चित समाधान होगा।

उचित निर्धारण हमेशा लॉक उत्तराधिकार का सम्मान करना है । एक आदेश चुनें जिसमें आप ताले प्राप्त करते हैं और उस पर चिपके रहते हैं। उदाहरण के लिए यदि दोनों थ्रेड्स हमेशा लॉक 2 से पहले लॉक 1 का अधिग्रहण करते हैं, तो गतिरोध की कोई संभावना नहीं है।


हाँ, मैं समझता हूँ कि। मैं इस तरह के एक वास्तविक कोड उदाहरण के लिए देख रहा हूँ। सवाल यह है कि "कदम एक तरफ" क्या मतलब है और यह इस तरह के परिदृश्य का उत्पादन कैसे करता है।
एलेक्स मिलर

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

यद्यपि यह एक स्थिर लाइवलॉक नहीं है, क्योंकि वे स्पष्ट रूप से इससे बाहर निकल जाएंगे, मुझे लगता है कि यह विवरण को अच्छी तरह से फिट करता है
1800 जानकारी

उत्कृष्ट और सार्थक उदाहरण।
ऐलेकोव

7

जैसा कि कोई जवाब नहीं है स्वीकृत उत्तर के रूप में, मैंने लाइव लॉक उदाहरण बनाने का प्रयास किया है;

मल्टीथ्रेडिंग की विभिन्न अवधारणा को सीखने के लिए अप्रैल 2012 में मेरे द्वारा मूल कार्यक्रम लिखा गया था। इस बार मैंने इसे गतिरोध, दौड़ की स्थिति, लाइवलॉक आदि बनाने के लिए संशोधित किया है।

तो आइए पहले समस्या कथन को समझते हैं;

कुकी निर्माता समस्या

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

कृपया गीथूब पर पूरा कोड जांचें ;

मैं आपको संक्षेप में कार्यान्वयन के बारे में बताता हूं।

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

आइए कोड में एक नज़र डालें:

CookieMaker.java

private Integer getMaterial(final Ingredient ingredient) throws Exception{
        :
        container.lock();
        while (!container.getIngredient(quantity)) {
            container.empty.await(1000, TimeUnit.MILLISECONDS);
            //Thread.sleep(500); //For deadlock
        }
        container.unlock();
        :
}

IngredientContainer.java

public boolean getIngredient(int n) throws Exception {
    :
    lock();
    if (quantityHeld >= n) {
        TimeUnit.SECONDS.sleep(2);
        quantityHeld -= n;
        unlock();
        return true;
    }
    unlock();
    return false;
}

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

मैंने एक डेमन थ्रेडट्रैसर भी बनाया है जो थ्रेड स्टेट्स और डेडलॉक पर नजर रखता है। यह कंसोल से आउटपुट;

2016-09-12 21:31:45.065 :: [Maker_0:WAITING, Maker_1:WAITING, Maker_2:WAITING, Maker_3:WAITING, Maker_4:WAITING, Maker_5:WAITING, Maker_6:WAITING, Maker_7:WAITING, pool-7-thread-1:TIMED_WAITING, pool-7-thread-2:TIMED_WAITING, pool-8-thread-1:TIMED_WAITING, pool-8-thread-2:TIMED_WAITING, pool-6-thread-1:TIMED_WAITING, pool-6-thread-2:TIMED_WAITING, pool-5-thread-1:TIMED_WAITING, pool-5-thread-2:TIMED_WAITING, pool-1-thread-1:TIMED_WAITING, pool-3-thread-1:TIMED_WAITING, pool-2-thread-1:TIMED_WAITING, pool-1-thread-2:TIMED_WAITING, pool-4-thread-1:TIMED_WAITING, pool-4-thread-2:RUNNABLE, pool-3-thread-2:TIMED_WAITING, pool-2-thread-2:TIMED_WAITING]
2016-09-12 21:31:45.065 :: [Maker_0:WAITING, Maker_1:WAITING, Maker_2:WAITING, Maker_3:WAITING, Maker_4:WAITING, Maker_5:WAITING, Maker_6:WAITING, Maker_7:WAITING, pool-7-thread-1:TIMED_WAITING, pool-7-thread-2:TIMED_WAITING, pool-8-thread-1:TIMED_WAITING, pool-8-thread-2:TIMED_WAITING, pool-6-thread-1:TIMED_WAITING, pool-6-thread-2:TIMED_WAITING, pool-5-thread-1:TIMED_WAITING, pool-5-thread-2:TIMED_WAITING, pool-1-thread-1:TIMED_WAITING, pool-3-thread-1:TIMED_WAITING, pool-2-thread-1:TIMED_WAITING, pool-1-thread-2:TIMED_WAITING, pool-4-thread-1:TIMED_WAITING, pool-4-thread-2:TIMED_WAITING, pool-3-thread-2:TIMED_WAITING, pool-2-thread-2:TIMED_WAITING]
WheatPowder Container has 0 only.
2016-09-12 21:31:45.082 :: [Maker_0:WAITING, Maker_1:WAITING, Maker_2:WAITING, Maker_3:WAITING, Maker_4:WAITING, Maker_5:WAITING, Maker_6:WAITING, Maker_7:WAITING, pool-7-thread-1:TIMED_WAITING, pool-7-thread-2:TIMED_WAITING, pool-8-thread-1:TIMED_WAITING, pool-8-thread-2:TIMED_WAITING, pool-6-thread-1:TIMED_WAITING, pool-6-thread-2:TIMED_WAITING, pool-5-thread-1:TIMED_WAITING, pool-5-thread-2:TIMED_WAITING, pool-1-thread-1:TIMED_WAITING, pool-3-thread-1:TIMED_WAITING, pool-2-thread-1:TIMED_WAITING, pool-1-thread-2:TIMED_WAITING, pool-4-thread-1:TIMED_WAITING, pool-4-thread-2:TIMED_WAITING, pool-3-thread-2:TIMED_WAITING, pool-2-thread-2:RUNNABLE]
2016-09-12 21:31:45.082 :: [Maker_0:WAITING, Maker_1:WAITING, Maker_2:WAITING, Maker_3:WAITING, Maker_4:WAITING, Maker_5:WAITING, Maker_6:WAITING, Maker_7:WAITING, pool-7-thread-1:TIMED_WAITING, pool-7-thread-2:TIMED_WAITING, pool-8-thread-1:TIMED_WAITING, pool-8-thread-2:TIMED_WAITING, pool-6-thread-1:TIMED_WAITING, pool-6-thread-2:TIMED_WAITING, pool-5-thread-1:TIMED_WAITING, pool-5-thread-2:TIMED_WAITING, pool-1-thread-1:TIMED_WAITING, pool-3-thread-1:TIMED_WAITING, pool-2-thread-1:TIMED_WAITING, pool-1-thread-2:TIMED_WAITING, pool-4-thread-1:TIMED_WAITING, pool-4-thread-2:TIMED_WAITING, pool-3-thread-2:TIMED_WAITING, pool-2-thread-2:TIMED_WAITING]

आप देखेंगे कि उप-सूत्र और उनके राज्य बदल रहे हैं और प्रतीक्षा कर रहे हैं।


4

एक वास्तविक (सटीक कोड के बिना यद्यपि) उदाहरण दो प्रतिस्पर्धी प्रक्रियाओं को SQL सर्वर गतिरोध के लिए सही करने के प्रयास में लाइव लॉकिंग है, प्रत्येक प्रक्रिया को पुन: प्रयास करने के लिए एक ही प्रतीक्षा-पुनरावृत्ति एल्गोरिथ्म का उपयोग करके किया जाता है। हालांकि यह समय की किस्मत है, मैंने एक ईएमएस विषय में जोड़े गए संदेश के जवाब में समान प्रदर्शन विशेषताओं के साथ अलग-अलग मशीनों पर ऐसा होता देखा है (उदाहरण के लिए एक बार से अधिक एकल ऑब्जेक्ट ग्राफ के अपडेट को सहेजना), और नियंत्रित करने में सक्षम नहीं होना। ताला आदेश।

इस मामले में एक अच्छा समाधान प्रतिस्पर्धी उपभोक्ताओं (असंबंधित वस्तुओं पर काम का विभाजन करके संभव के रूप में श्रृंखला में डुप्लिकेट प्रसंस्करण को रोकने के लिए) होगा।

एक कम वांछनीय (ठीक, गंदा-हैक) समाधान अग्रिम में समय खराब भाग्य (प्रसंस्करण में बल अंतर की तरह) को तोड़ने या अलग-अलग एल्गोरिदम या यादृच्छिकता के कुछ तत्व का उपयोग करके गतिरोध के बाद इसे तोड़ना है। यह अभी भी समस्या हो सकती है क्योंकि प्रत्येक प्रक्रिया के लिए ताला लेने का आदेश "चिपचिपा" है, और प्रतीक्षा-रिट्री में इसका एक न्यूनतम न्यूनतम समय लगता है।

फिर भी एक अन्य समाधान (कम से कम SQL सर्वर के लिए) एक अलग अलगाव स्तर (जैसे स्नैपशॉट) की कोशिश करना है।


2

मैंने गलियारे में गुजर रहे 2 व्यक्तियों का उदाहरण दिया। जैसे ही उन्हें पता चलता है कि दोनों धागे एक-दूसरे से बचेंगे, वे एक ही हैं।

public class LiveLock {
    public static void main(String[] args) throws InterruptedException {
        Object left = new Object();
        Object right = new Object();
        Pedestrian one = new Pedestrian(left, right, 0); //one's left is one's left
        Pedestrian two = new Pedestrian(right, left, 1); //one's left is two's right, so have to swap order
        one.setOther(two);
        two.setOther(one);
        one.start();
        two.start();
    }
}

class Pedestrian extends Thread {
    private Object l;
    private Object r;
    private Pedestrian other;
    private Object current;

    Pedestrian (Object left, Object right, int firstDirection) {
        l = left;
        r = right;
        if (firstDirection==0) {
            current = l;
        }
        else {
            current = r;
        }
    }

    void setOther(Pedestrian otherP) {
        other = otherP;
    }

    Object getDirection() {
        return current;
    }

    Object getOppositeDirection() {
        if (current.equals(l)) {
            return r;
        }
        else {
            return l;
        }
    }

    void switchDirection() throws InterruptedException {
        Thread.sleep(100);
        current = getOppositeDirection();
        System.out.println(Thread.currentThread().getName() + " is stepping aside.");
    }

    public void run() {
        while (getDirection().equals(other.getDirection())) {
            try {
                switchDirection();
                Thread.sleep(100);
            } catch (InterruptedException e) {}
        }
    }
} 

2

जेलबर्न के कोड का C # संस्करण:

using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

namespace LiveLockExample
{
    static class Program
    {
        public static void Main(string[] args)
        {
            var husband = new Diner("Bob");
            var wife = new Diner("Alice");

            var s = new Spoon(husband);

            Task.WaitAll(
                Task.Run(() => husband.EatWith(s, wife)),
                Task.Run(() => wife.EatWith(s, husband))
                );
        }

        public class Spoon
        {
            public Spoon(Diner diner)
            {
                Owner = diner;
            }


            public Diner Owner { get; private set; }

            [MethodImpl(MethodImplOptions.Synchronized)]
            public void SetOwner(Diner d) { Owner = d; }

            [MethodImpl(MethodImplOptions.Synchronized)]
            public void Use()
            {
                Console.WriteLine("{0} has eaten!", Owner.Name);
            }
        }

        public class Diner
        {
            public Diner(string n)
            {
                Name = n;
                IsHungry = true;
            }

            public string Name { get; private set; }

            private bool IsHungry { get; set; }

            public void EatWith(Spoon spoon, Diner spouse)
            {
                while (IsHungry)
                {
                    // Don't have the spoon, so wait patiently for spouse.
                    if (spoon.Owner != this)
                    {
                        try
                        {
                            Thread.Sleep(1);
                        }
                        catch (ThreadInterruptedException e)
                        {
                        }

                        continue;
                    }

                    // If spouse is hungry, insist upon passing the spoon.
                    if (spouse.IsHungry)
                    {
                        Console.WriteLine("{0}: You eat first my darling {1}!", Name, spouse.Name);
                        spoon.SetOwner(spouse);
                        continue;
                    }

                    // Spouse wasn't hungry, so finally eat
                    spoon.Use();
                    IsHungry = false;
                    Console.WriteLine("{0}: I am stuffed, my darling {1}!", Name, spouse.Name);
                    spoon.SetOwner(spouse);
                }
            }
        }
    }
}

1

यहां एक उदाहरण एक से अधिक लॉक प्राप्त करने के लिए समयबद्ध कोशिश का उपयोग कर सकता है और यदि आप उन सभी को प्राप्त नहीं कर सकते हैं, तो वापस बंद करें और फिर से प्रयास करें।

boolean tryLockAll(Collection<Lock> locks) {
  boolean grabbedAllLocks = false;
  for(int i=0; i<locks.size(); i++) {
    Lock lock = locks.get(i);
    if(!lock.tryLock(5, TimeUnit.SECONDS)) {
      grabbedAllLocks = false;

      // undo the locks I already took in reverse order
      for(int j=i-1; j >= 0; j--) {
        lock.unlock();
      }
    }
  }
}

मैं सोच सकता हूं कि इस तरह का कोड समस्याग्रस्त होगा क्योंकि आपके पास बहुत सारे धागे टकरा रहे हैं और ताले का एक सेट प्राप्त करने की प्रतीक्षा कर रहे हैं। लेकिन मुझे यकीन नहीं है कि यह एक सरल उदाहरण के रूप में मेरे लिए बहुत सम्मोहक है।


1
इसके लिए एक लाइवलॉक होने के लिए आपको एक अलग क्रम में उन तालों को प्राप्त करने के लिए एक और धागे की आवश्यकता होगी। यदि सभी धागे एक ही क्रम में tryLockAll()ताले के साथ उपयोग करते हैं locks, तो कोई लाइवलॉक नहीं है।
JaviMerino

0

जेलबोर्न के कोड का पायथन संस्करण:

import threading
import time
lock = threading.Lock()

class Spoon:
    def __init__(self, diner):
        self.owner = diner

    def setOwner(self, diner):
        with lock:
            self.owner = diner

    def use(self):
        with lock:
            "{0} has eaten".format(self.owner)

class Diner:
    def __init__(self, name):
        self.name = name
        self.hungry = True

    def eatsWith(self, spoon, spouse):
        while(self.hungry):
            if self != spoon.owner:
                time.sleep(1) # blocks thread, not process
                continue

            if spouse.hungry:
                print "{0}: you eat first, {1}".format(self.name, spouse.name)
                spoon.setOwner(spouse)
                continue

            # Spouse was not hungry, eat
            spoon.use()
            print "{0}: I'm stuffed, {1}".format(self.name, spouse.name)
            spoon.setOwner(spouse)

def main():
    husband = Diner("Bob")
    wife = Diner("Alice")
    spoon = Spoon(husband)

    t0 = threading.Thread(target=husband.eatsWith, args=(spoon, wife))
    t1 = threading.Thread(target=wife.eatsWith, args=(spoon, husband))
    t0.start()
    t1.start()
    t0.join()
    t1.join()

if __name__ == "__main__":
    main()

कीड़े: उपयोग में (), प्रिंट का उपयोग नहीं किया जाता है और - इससे भी महत्वपूर्ण बात - भूखे झंडे को गलत पर सेट नहीं किया जाता है।
GDR

0

मैं @jelbourn के उत्तर को संशोधित करता हूं। जब उनमें से एक ने यह नोटिस किया कि दूसरा भूखा है, उसे (उसे) चम्मच छोड़ना चाहिए और दूसरी सूचना का इंतजार करना चाहिए, इसलिए एक लाइवलॉक होता है।

public class LiveLock {
    static class Spoon {
        Diner owner;

        public String getOwnerName() {
            return owner.getName();
        }

        public void setOwner(Diner diner) {
            this.owner = diner;
        }

        public Spoon(Diner diner) {
            this.owner = diner;
        }

        public void use() {
            System.out.println(owner.getName() + " use this spoon and finish eat.");
        }
    }

    static class Diner {
        public Diner(boolean isHungry, String name) {
            this.isHungry = isHungry;
            this.name = name;
        }

        private boolean isHungry;
        private String name;


        public String getName() {
            return name;
        }

        public void eatWith(Diner spouse, Spoon sharedSpoon) {
            try {
                synchronized (sharedSpoon) {
                    while (isHungry) {
                        while (!sharedSpoon.getOwnerName().equals(name)) {
                            sharedSpoon.wait();
                            //System.out.println("sharedSpoon belongs to" + sharedSpoon.getOwnerName())
                        }
                        if (spouse.isHungry) {
                            System.out.println(spouse.getName() + "is hungry,I should give it to him(her).");
                            sharedSpoon.setOwner(spouse);
                            sharedSpoon.notifyAll();
                        } else {
                            sharedSpoon.use();
                            sharedSpoon.setOwner(spouse);
                            isHungry = false;
                        }
                        Thread.sleep(500);
                    }
                }
            } catch (InterruptedException e) {
                System.out.println(name + " is interrupted.");
            }
        }
    }

    public static void main(String[] args) {
        final Diner husband = new Diner(true, "husband");
        final Diner wife = new Diner(true, "wife");
        final Spoon sharedSpoon = new Spoon(wife);

        Thread h = new Thread() {
            @Override
            public void run() {
                husband.eatWith(wife, sharedSpoon);
            }
        };
        h.start();

        Thread w = new Thread() {
            @Override
            public void run() {
                wife.eatWith(husband, sharedSpoon);
            }
        };
        w.start();

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        h.interrupt();
        w.interrupt();

        try {
            h.join();
            w.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

0
package concurrently.deadlock;

import static java.lang.System.out;


/* This is an example of livelock */
public class Dinner {

    public static void main(String[] args) {
        Spoon spoon = new Spoon();
        Dish dish = new Dish();

        new Thread(new Husband(spoon, dish)).start();
        new Thread(new Wife(spoon, dish)).start();
    }
}


class Spoon {
    boolean isLocked;
}

class Dish {
    boolean isLocked;
}

class Husband implements Runnable {

    Spoon spoon;
    Dish dish;

    Husband(Spoon spoon, Dish dish) {
        this.spoon = spoon;
        this.dish = dish;
    }

    @Override
    public void run() {

        while (true) {
            synchronized (spoon) {
                spoon.isLocked = true;
                out.println("husband get spoon");
                try { Thread.sleep(2000); } catch (InterruptedException e) {}

                if (dish.isLocked == true) {
                    spoon.isLocked = false; // give away spoon
                    out.println("husband pass away spoon");
                    continue;
                }
                synchronized (dish) {
                    dish.isLocked = true;
                    out.println("Husband is eating!");

                }
                dish.isLocked = false;
            }
            spoon.isLocked = false;
        }
    }
}

class Wife implements Runnable {

    Spoon spoon;
    Dish dish;

    Wife(Spoon spoon, Dish dish) {
        this.spoon = spoon;
        this.dish = dish;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (dish) {
                dish.isLocked = true;
                out.println("wife get dish");
                try { Thread.sleep(2000); } catch (InterruptedException e) {}

                if (spoon.isLocked == true) {
                    dish.isLocked = false; // give away dish
                    out.println("wife pass away dish");
                    continue;
                }
                synchronized (spoon) {
                    spoon.isLocked = true;
                    out.println("Wife is eating!");

                }
                spoon.isLocked = false;
            }
            dish.isLocked = false;
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.