Concurrence

Retour sur le TP2 : question optionnelle


HelloListBug2

Le code de add

Dans la classe ArrayList :

  private Object[] grow(int minCapacity) {
      return elementData = Arrays.copyOf(elementData, newCapacity(minCapacity));
  }
  
  private Object[] grow() {
      return grow(size + 1);  // renvoie un tab. de cette taille au minimum 
  }                           // (mais plus probablement dont la taille est doublée)
  
  private void add(E e, Object[] elementData, int s) {
      if (s == elementData.length)
          elementData = grow(); // renvoie un tab. plus grand
      elementData[s] = e;
      size = s + 1;
  }
  
  public boolean add(E e) {
      modCount++;
      add(e, elementData, size);
      return true;
  }

Dans le cas où la capacité initiale est fixée et assez grande, grow() n'est jamais appelée. Mais sinon, cela arrive quand le tableau elementData est rempli.

Scénario possible

  • On suppose que pour la taille de elementData est 128.
  • T1 est schédulé, il fait l'appel list.add(?). Supposons qu'à ce moment là size (et donc le paramètre s) vaut 13.
    T1 est dé-schédulé entre elementData[s] = e et size = s + 1.
  • T2 est schédulé fait l'appel list.add(?). Le champs size vaut 13 et T2 garde la main pendant quelques temps. Il arrive au moment où size vaut 128. Il rentre dans list.add(?, elementData, 128).
    Le paramètre s vaut 128, donc T2 passe le test du if et devrait ensuite appeler grow() puis faire appel à grow(129) (c'est à dire size + 1). Mais il est dé-schédulé juste avant le grow().
  • T1 est schédulé, il écrit size = 14 puis il est dé-schédulé.
  • T2 est schédulé, il appelle grow(15) (c'est à dire size + 1), ce qui remplace elementData par un tableau de taille 30 (environ).
    Puis il effectue l'instruction elementData[128] = ? alors que le tableau n'a que 30 cases, ce qui lève une ArrayIndexOutOfBoundsException.