লাইভলকের ভালো উদাহরণ?


141

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


96
একজন করিডরে একে অপরকে পাশ কাটিয়ে যাওয়ার চেষ্টা করা দু'জনের সফ্টওয়্যার সিমুলেশন সম্পর্কে কীভাবে?
1800 তথ্য

36
অভিশাপ! আমি আমার মধ্যাহ্নভোজন!
অ্যালেক্স মিলার

3
অদ্ভুতভাবে উপযুক্ত: seuss.wikia.com/wiki/The_Zax
নোটমে

কৌতূহলী fellas
জোর্জন

4
দুই জনের একটি দালান একে অপরের গত পেতে চেষ্টা: gist.github.com/deepankarb/d2dd6f21bc49902376e614d3746b8965 : P
বরফ মানব

উত্তর:


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। এই
ভিডটি

2
পদ্ধতির synchronized জন্য আপনার কীওয়ার্ড ব্যবহার করার দরকার নেই setOwner, কারণ পড়া এবং লেখাই রেফারেন্স ভেরিয়েবলের জন্য পারমাণবিক ক্রিয়া।
আতিকখালেদ

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 অর্জন করে, তবে অচলাবস্থার কোনও সম্ভাবনা নেই।


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

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

যদিও এটি একটি স্থিতিশীল লাইভলক নয় কারণ তারা স্পষ্টতই এর থেকে বিচ্ছিন্ন হয়ে যাবে, আমি মনে করি এটি বিবরণটি যথেষ্ট পরিমাণে ফিট করে
1800 তথ্য

দুর্দান্ত এবং অর্থবহ উদাহরণ।
আলেকোভ

7

গৃহীত উত্তর হিসাবে চিহ্নিত কোনও উত্তর না থাকায় আমি লাইভ লক উদাহরণ তৈরি করার চেষ্টা করেছি;

মূল প্রোগ্রামটি আমার দ্বারা লিখেছিল এপ্রিল ২০১২ এ মাল্টিথ্রেডিংয়ের বিভিন্ন ধারণাটি শিখতে। এবার আমি এটিকে সংশোধন করে অচলাবস্থা, রেসের শর্ত, লাইভলক ইত্যাদি তৈরি করেছি

সুতরাং আসুন প্রথমে সমস্যার বিবৃতিটি বুঝতে পারি;

কুকি প্রস্তুতকারকের সমস্যা

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

গিথুব এ সম্পূর্ণ কোড পরীক্ষা করুন ;

আমি আপনাকে সংক্ষেপে বাস্তবায়ন ব্যাখ্যা করতে দিন।

  • আমি ডিমন থ্রেড হিসাবে ফিলার শুরু করি । সুতরাং এটি নিয়মিত বিরতিতে পাত্রগুলি পূরণ করতে থাকবে। প্রথমে একটি ধারক পূরণ করার জন্য এটি ধারকটি লক করে -> এটির জন্য কোনও গুঁড়ো দরকার কিনা তা পরীক্ষা করে দেখুন -> এটি পূরণ করে -> সমস্ত নির্মাতারা যারা এর জন্য অপেক্ষা করছেন -> কনটেইনারটি আনলক করুন signal
  • আমি কুকি মেকার তৈরি করেছি এবং সেট করেছি যে এটি সমান্তরালে 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

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

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

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

তবুও আরেকটি সমাধান (কমপক্ষে এসকিউএল সার্ভারের জন্য) একটি আলাদা বিচ্ছিন্নতা স্তরের চেষ্টা করা (যেমন স্ন্যাপশট)।


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

সি # জেলব্রোন কোডের সংস্করণ:

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কোনও লাইভলক নেই।
জাভিমারিনো

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()

বাগগুলি: ব্যবহারে (), মুদ্রণ ব্যবহৃত হয় না এবং - আরও গুরুত্বপূর্ণভাবে - ক্ষুধার্ত পতাকাটি মিথ্যাতে সেট করা হয় না।
জিডিআর

0

আমি @ জেলব্রন এর উত্তরটি পরিবর্তন করেছি। যখন তাদের মধ্যে কেউ খেয়াল করে যে অন্যটি ক্ষুধার্ত হয়েছে, তার (তার) চামচটি ছেড়ে দেওয়া উচিত এবং অন্য কোনও বিজ্ঞপ্তির অপেক্ষা করা উচিত, যাতে একটি লাইভলক ঘটে।

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