2009-07-19 7 views
0

Je fais quelques exercices avec Java (certains d'entre vous peuvent supposer d'où vient le code). J'essaie de provocate un deadlocksituation avec le code suivant:Java impasseprovocation

class Resource { 

    public Integer value = 42; 
} 

public class DeadLockRisk implements Runnable { 

    private Resource resourceA = new Resource(); 
    private Resource resourceB = new Resource(); 

    public void write(int a, int b) { 

     System.out.println(Thread.currentThread().getName() + " try write Lock A"); 

     synchronized(resourceA) { 

      System.out.println(Thread.currentThread().getName() + " write Lock A"); 
      System.out.println(Thread.currentThread().getName() + " try write Lock B"); 

      synchronized(resourceB) { 

       System.out.println(Thread.currentThread().getName() + " write Lock B"); 

       resourceA.value = a; 
       resourceB.value = b; 
     //sit on it! 
     //try { Thread.sleep(5000); } catch (Exception e) {} 

     System.out.println(Thread.currentThread().getName() + " release write B"); 
     } 
     System.out.println(Thread.currentThread().getName() + " release write A"); 
    } 
    } 

    public int read() { 

    Integer retVal; 
     System.out.println(Thread.currentThread().getName() + " try read Lock B"); 

     synchronized(resourceB) { 

      System.out.println(Thread.currentThread().getName() + " read Lock B"); 
      System.out.println(Thread.currentThread().getName() + " try read Lock A"); 

      synchronized(resourceA) { 

       System.out.println(Thread.currentThread().getName() + " read Lock A"); 
       retVal = resourceB.value + resourceA.value; 
     System.out.println(Thread.currentThread().getName() + " release read A"); 
      } 
     System.out.println(Thread.currentThread().getName() + " release read B"); 
     } 
    return retVal; 
    } 

    public void run() { 


    if (Thread.currentThread().getName().equals("Thread-1")) { 
     write(1,2); 
    } 

    System.out.println(read()); 
    } 

    public static void main(String[] args) { 

     Thread ta = new Thread(new DeadLockRisk()); 
     Thread tb = new Thread(new DeadLockRisk()); 
     ta.start(); tb.start(); 
    } 
} 

(javac javac -version 1.6.0_0 uname -a Linux 2.6.29 inspiron # 1 SMP sam 16 mai 10:56:17 CEST 2009 i686 GNU/Linux)

et obtenir (entre autres) pour la sortie ci-dessous:

 
Thread-1 try write Lock A 
Thread-0 try read Lock B 
Thread-1 write Lock A  <===== 
Thread-0 read Lock B 
Thread-1 try write Lock B 
Thread-0 try read Lock A 
Thread-1 write Lock B 
Thread-0 read Lock A  <===== 
Thread-1 release write B 
Thread-0 release read A 
Thread-1 release write A 
Thread-0 release read B 
Thread-1 try read Lock B 
154 
Thread-1 read Lock B 
Thread-1 try read Lock A 
Thread-1 read Lock A 
Thread-1 release read A 
Thread-1 release read B 
3 

Qu'est-ce que je vois mal? Comment Thread-0 peut-il même entrer dans la section critique de read() et obtenir le verrou sur A, avant que le verrou ne soit libéré par Thread-1. Est-ce possible parce que la sortie n'est pas synchrone? Deadlock ne se produit jamais avec ce code.

Répondre

5

Vous passez une instance différente de DeadLockRisk aux deux threads, ils ne sont donc pas synchronisés sur les mêmes objets.

+0

ups, vous êtes rapide, et je suis stupide ;-), merci –

+0

@ justus.gadient.xyon, si vous aimez cette réponse, s'il vous plaît cliquer sur l'icône de cocher sur la gauche pour le sélectionner comme «la réponse» – akf

1

Les deux instances de DeadlockRisk ont ​​des instances différentes pour les champs resourceA et resourceB. Si vous voulez que le code fonctionne comme prévu, changez les champs d'instance en champs statiques.

+0

1 ms, et nous avons le désordre ;-) ... java/examples $ java DeadLockRisk discussion-0 essayez de lire cette discussion-1 verrouillage B essayer un verrou en écriture A thread-0-1 discussion lire verrouillage B write Lock A Thread-0 essaie de lire Lock A Thread-1 essaie d'écrire Lock B –