سؤال

أحاول أن أتعلم Jist الأساسية لسيارة الإشارة في مشكلة فيلسوف تناول الطعام. في الوقت الحالي ، لدي مجموعة من ختم الفئة ، ولكل من عيدان الفئة مربعًا مع تصريح واحد متاح:

public class Chopstick
{
    Thread holder = null;
    private Semaphore lock = new Semaphore(1);

    public synchronized void take() throws InterruptedException
    {
        this.lock.acquire();
        holder = Thread.currentThread();

    }

    public synchronized void release()
    {   
        this.lock.release();
        holder = null;
    }
}

يتم استخدام متغير الحامل لوظيفة لست متأكدًا من أنني بحاجة إليها:

public synchronized void conditionalRelease()
{
    if (holder == Thread.currentThread())
    {
        holder = null;
        this.lock.release();
    }
}

يقوم البرنامج بتجميع ويدير ، ولكن يبدو أنه يواجه بعض المتاعب في إطلاق سرطان تناول الطعام. في بعض الأحيان ، يتم إطلاق سراح عيدان تناول الطعام ، وأحيانًا لا يفعلون ذلك. عندما لا يصدرون ، يتم تعليق البرنامج في نهاية المطاف عندما يتم أخذ جميع مقصات تناول الطعام ويكون فيلسوف جائعًا.

فيما يلي الرمز داخل فئة الفيلسوف لإصدار عيدان تناول الطعام بعد فترة زمنية عشوائية:

System.out.println(this.name + " is eating");
Thread.sleep(this.getRandTime());
System.out.println(this.name + " has finished eating");

rightChopstick.release();
System.out.println(this.name + " has released the right chopstick");
leftChopstick.release();
System.out.println(this.name + " has released the left chopstick");

يقوم برنامجي بإخراج "Viropher 0 انتهى الأكل" ، على سبيل المثال ، ويستمر في التنفيذ. لا يخرج الخطان الآخران أبدًا ، لذلك من الواضح أن هناك خطأ ما في الطريقة التي أطلق بها.

أي مساعدة موضع تقدير.

هل كانت مفيدة؟

المحلول

أود أن أخرج الكلمة الرئيسية "المتزامنة" من توقيعات الطريقة. أنت تستخدم آلية قفل خارجية (Semaphore ، في هذه الحالة). تحاول الكلمة الرئيسية "المتزامنة" الحصول على أقفال باستخدام Mutex الخاص بالكائن. أنت الآن تغلق على موارد أظن أنها قد تسبب طريق مسدود.

نصائح أخرى

تكمن المشكلة في أنه عندما يكون لـ Thread1 مقصة محددة ويحاول آخر الحصول على نفس الشخص الذي سينتظر في take()-أولى على الإنترنت this.lock.acquire(); لكنه سيبقى ليس حرر الشاشة على الكائن نفسه.

إذا حاول الآن Thread1 إطلاق سراح عيدان ، فإنه لا يمكن إدخال release()-لقياح لأنه لا يزال مغلقًا من الخيط الآخر ينتظر في take(). هذا طريق مسدود

يبدو من المربك بعض الشيء أنكما تقفلان على عيدان تناول الطعام وتجعله يحتفظ بحجم واحد. إما كتلة متزامنة أو كائن قفل). قد تفكر بالفعل في صنع كائن القفل نفسه.

قمت بنشر مدونة على فلاسفة تناول الطعام في جافا بعد فترة من الوقت إذا كنت مهتمًا ، على الرغم من أن الأمر يتعلق حقًا بكيفية تجنب الجمود باستخدام استراتيجيات أخرى.

تأكد من عدم وجود أي كلمة رئيسية قفل أو متزامنة. الرمز أدناه لعصا التقطيع يعمل بشكل جيد بالنسبة لي .. ليس محترفًا ولكن يجب أن يعطيك بعض الأفكار ؛

public class Chopstick {
private boolean inuse;
Semaphore sem;

public Chopstick(){

    inuse = false;
    sem = new Semaphore(1);
}
public void pickUp()
{
    try
    {
        while(inuse)
        {
            try
            {
                sem.acquire();

            }
            catch(InterruptedException e) {}
        }
        inuse = true;
    }catch(Exception e){}
}
public void putDown()
{
    try
    {
        inuse = false;
        sem.release();

    }
    catch (Exception e){}
}

}

يحتاج Philspher إلى الحصول على القفل على كل من Chosticks قبل البدء في تناول الطعام وسيقوم بالتقاط LeftOne أولاً ثم انتظر حتى يتم التغلب على الأكل بحيث يجب مزامنة طريقة البدء. الأساليب التالية ستجعلها تعمل:

public synchronized void startEating() {
    leftChopstick.acquire();
    rightChopstick.acquire();
}

public void finishEating(int id) {
    leftChopstick.release();
    rightChopstick.release();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top