เกี่ยวกับ deadlock

เริ่มโดย korakotz, 23 ตุลาคม 2013, 10:44:33

หัวข้อก่อนหน้า - หัวข้อถัดไป

0 สมาชิก และ 1 ผู้มาเยือน กำลังดูหัวข้อนี้

korakotz

สวัสดีครับ ขอปรึกษาเรื่อง การทำให้โปรแกรมเกิด deadlock แล้วใช้วิธีแก้ปัญหาโดยใช้ Semaphore กับ Monitor(synchronization)(เอามาจากพิวกิไม่รู้ว่าถูกหรือเปล่า) ตอนนี้ผมคิดว่าผมเขียนโค็ตให้เกิด deadlock ได้ดังนี้ครับ
public class Deadlock5{
    /*private static final Object obj1 = "resource1";
    private static final Object obj2 = "resource2";*/
   
    //semaphore
    private static final Semaphore obj1 = new Semaphore(1);
    private static final Semaphore obj2 = new Semaphore(1);
   
    public static void main(String[] args) throws Exception {
     
        obj1.acquire();
        obj2.acquire();
        Thread t1 = new Thread(new p1());
        Thread t2 = new Thread(new p2());
        t1.start();
        t2.start();
    }
    public static class p1 implements Runnable {
       
        @Override
        public void run(){
           
           
            try{
               
                synchronized(obj1){
                    System.out.println("Thread1 acquired lock on resource1");
                    Thread.sleep(100);
                    obj1.release();
                   
                synchronized(obj2){
                System.out.println("Thread1 acquired lock on resource2");
                System.out.println("finish");
            }
                }
               
            }
            catch(InterruptedException e){System.out.println("Process interrupted....");}
           
               
            }
        }
   
    public static class p2 implements Runnable {
        @Override
        public void run(){
           
                try{
                   
                    synchronized(obj2){
                System.out.println("Thread2 acquired lock on resource2");
                Thread.sleep(100);
                obj2.release();
               
                 synchronized(obj1){
                System.out.println("Thread2 acquired lock on resource1");
                System.out.println("finish");
            }
                    }
                   
                 
                }
                catch(InterruptedException e){System.out.println("Process interrupted....");}
           
            }
        }
       
    }


เมื่อ run โปรแกรม จะเกิดdeadlock ขึ้น โดย Thread 1 จะไปlock resource 1 แล้ว พยายามจะไป lock resource2 แต่เนื่องจาก Thread2 ได้lock resource 2 ไว้ก่อนแล้วจึง รอให้ Thread2 ปล่อย resource นั้น เช่นกัน Thread2 ก็พยายามจะ lock resource 1
จึงทำให้เกิด deadlock ขึ้น

ปัญหาอยู่ที่ว่า ผมจะใช้ Semaphore จาก java conCurrent semaphore แต่ไม่รู้ว่าจะใช้ acquire() กับ release() ในช่วงใหนครับ

ขอคำแนะนำหน่อยครับ ว่าผมมาถูกทางหรือไม่ หรือมาผิดทาง(โค็ตผิด) แล้วใช้ monitor algorithm แก้ปัญหานี้อย่างไรครับ

korakotz

เข้ามาดันเพื่อมีใครพอจะช่วยได้บ้าง  :wanwan031:

MapTwoZa

1. thread มันคุมไม่ได้ครับ ดังนั้น รอบเดียว อาจจะยังไม่เกิด lock ดังนั้น ถ้าจะให้เกิด lock ใน thread 2 ตัว ต้องวนลูป accire/release เรื่อยๆ เด๋วมันจะติด lock เอง (เพื่อความชัวร์)

ขั้นตอนใน thread แต่ละตัวก็
#thread1
1. acquire semaphore 1
2. do something
3. acquire semaphore 2
4. do something
5. release semaphore 2
6. release semaphore 1

#thread2
1. aqquire semaphore 2
2. do something
3. acquire semaphore 1
4. do something
5. release semaphore 1
6. release semaphore 2


ประมาณนี้ครับ

ขั้นตอนปรกติ ของการ deadlock น่าจะประมาณนี้
X starts to use A.
X and Y try to start using B
Y 'wins' and gets B first
now Y needs to use A
A is locked by X, which is waiting for Y
Good code quality Developer :D

korakotz

คือจะใช้ Semaphore algorithm แก้ไขปัญหา deadlock อะครับ :wanwan031:

โค็ดที่เขียนหากไม่รวม Semaphore (ac,re) และเอาคอมเม้น   /*private static final Object obj1 = "resource1";
    private static final Object obj2 = "resource2";*/ ออกไปคอมเม้นตรอง semaphore แทนมันก็เกิด deadlock ครับ

MapTwoZa

#4
โทษที ผมเมาครับ อ่านไม่ดี 55+

แก้ dead lock ในกรณีมีการใช้งานหลายๆ resource ร่วมกัน

วิธีที่ 1. ถ้าเกิด acquire ไม่ได้ ให้ release ทิ้งให้หมดเลย อันนี้เป็น optimistic case คือกันไว้ แต่โอกาสเกิดน้อยมากๆ
วิธีที่ 2. ถ้าเกิด acquire ไม่ได้ ให้รอระยะเวลานึง ถ้าครบเวลาแล้ว ยัง acquire ไม่ได้ ให้ release ของตัวเองทิ้งให้หมดเลย อันนี้เป็น permistic case ถ้าเห็นว่ามีโอกาสเกิด แต่ตรงนี้ต้องระวังเรื่องการ wait ถ้า wait นานไปจะเป็นคอขวด

ส่วนหลังจาก release เพราะ acquire ไม่ได้นั้น จะ throw exception หรือไปเข้าคิวใหม่ก็แล้วแต่

ส่วนเรื่อง code ลองเขียนเองเลยครับ

ปล. ไอ 2 ข้อนั้นคือกันเหนียวนะครับ จริงๆควรหลีกเลี่ยงการเขียน code ที่จะทำให้เกิด deadlock ครับ


เพิ่มเติม
ผม implement แบบ permistic เป็นแนวทางให้ละกัน


public class Resource{
 private int poolCount = 1;  // number of available resource
 public Object acquire(){
   syncronized(this){
     if(this.poolCount ==0){
        wait(2); // waiting for 2 second
        // double locking to check
        if(poolCount == 0){
            return null;
        }
     }

     // resouce acquiring
     this.poolCount--;
     return xxx;
   }

}

 public void release(){
   this.poolCount++;
   this.notify();
 }

}


ทีนี้ตอน acquire ก็เช็คก่อน ถ้า acquire แล้วได้ null ก็ release resource ตัวเองทิ้งให้หมด
Good code quality Developer :D