A thread que primeiro se refere a uma classe deve inicializá-la. Por exemplo, considere esta interface:

interface Constantes {
    int[] IARRAY = { 42 };
}

A thread que se referir primeiro a esta interface irá inicializá-la; entre outras coisas, esta tarefa inclui criar um vetor com um elemento inteiro, atribuir o valor 42 a este elemento e armazenar a referência ao vetor na variável IARRAY.

Agora, veja a classe seguinte (que utiliza a interface Constantes):

class Foo implements Runnable {
    public static void main(String[] args) {
        Foo f = new Foo();
        Thread t1 = new Thread(f), t2 = new Thread(f);
        t1.start(); t2.start();
    }
    public void run() { 
        System.out.println(Constants.IARRAY[0]);
    }
}

Suponha que t1 seja a primeira thread que alcança a linha onde o valor de IARRAY[0] é exibido. Então, t1 precisa inicializar a interface Constantes e, de acordo com as regras de Java, se t2 também atingir esta linha, deve esperar até que a inicialização tenha se completado (ou seja, Java não permite que t2 inicialize a interface Constantes se outra thread já está fazendo o mesmo, nem permite que t2 veja o valor de IARRAY[0] enquanto a inicialização não acabar).

Um problema com o algoritmo Dinning-Schonberg é que ele não leva em conta essa regra da linguagem Java, e, para um código como no exemplo acima, o algoritmo pode emitir alarmes sobre condições de disputa que de fato não existem. Para prevenir estes alarmes falsos, você pode selecionar a opção Ignorar inicialização de classes. Por outro lado, condições de disputa verdadeiras (como no exemplo a seguir, envolvendo a variável Main.pi), serão perdidas se essa opção estiver selecionada:

interface Y {
    float PI = Main.pi;
}

class Main {
    static float pi = 2.14;
    public static void main(String[] args) {
        new Thread() {
            public void run() {
                System.out.println(Y.PI); // pode imprimir 2.14 ou 3.14
            }
        }
        Main.pi++;
    }
}
A opção para ignorar a inicialização de classes não faz sentido com Eraser (que automaticamente ignora a inicialização de variáveis, em particular durante a inicialicação de classes), mas note que Eraser pode perder uma condição de disputa como a mostrada no exemplo anterior.

Voltar.