Состояние гонки в линейной java-программе

прилагаемый программный код большую часть времени выдает следующий вывод:

6.0
8.0
10.0
12.0

java.lang.RuntimeException: dimensions not matching
    at hausaufgaben.linearAlgebra1.VectorRn.add(VectorRn.java:41)
    at hausaufgaben.linearAlgebra1.VectorRn.main(VectorRn.java:19)

3.0
6.0
9.0
12.0

но при втором выполнении он выдал следующий вывод

6.0
8.0
10.0
12.0

java.lang.RuntimeException: dimensions not matching
3.0
6.0
9.0
12.0

    at hausaufgaben.linearAlgebra1.VectorRn.add(VectorRn.java:41)
    at hausaufgaben.linearAlgebra1.VectorRn.main(VectorRn.java:19)

означает ли это, что в простых программах с выводом на консоль уже есть условия гонки, которые ведут себя детерминировано в 99,99% случаев?

или оператор catch выполняется в отдельном потоке?

или console.output настроен странно?

Я смущен тем, как что-то подобное могло произойти, даже если это редкость.

package hausaufgaben.linearAlgebra1;

public class VectorRn {
/**
 * values that are the components
 */
private double[] values;

/**
 * @param args
 */
public static void main(String[] args) {
    VectorRn a = new VectorRn(1,2,3,4);
    VectorRn b = new VectorRn(5,6,7,8);
    VectorRn c = new VectorRn(1,2);
    double d = 3;
    System.out.println(a.add(b).toString());
    try {
        System.out.println(a.add(c).toString());
    }catch(Exception e) {
        e.getMessage();
        e.printStackTrace();
    }
    System.out.println("\n"+a.mult(d).toString());
}    

/**
 * @param values copies the values passed to the constructor
 */
public VectorRn(double... values) {
    this.values = new double[values.length];
    System.arraycopy(values, 0, this.values, 0, values.length);
}

/**
 * @param v2 the vector added to a clone of this object
 * @return the sum of this Vector and v2
 */
public VectorRn add(VectorRn v2) {
    if(this.values.length != v2.values.length)
        throw new RuntimeException("dimensions not matching");
    VectorRn modifiedClone = new VectorRn(this.values);
    for(int i = 0; i < modifiedClone.values.length; i++){
        modifiedClone.values[i] += v2.values[i];
    }
    return modifiedClone;
}


/**
 * @param d the scalar by which the clone of this object will be multiplied
 * @return the d'th multiple of this Vector
 */
public VectorRn mult(double d) {
    VectorRn modifiedClone = new VectorRn(this.values);
    for(int i = 0; i < this.values.length; i++) {
        modifiedClone.values[i] *= d;
    }
    return modifiedClone;
}

/**
 * @return a string that contains a list of the components of the vector separated by newline characters
 * @see java.lang.Object#toString()
 */
public String toString() {
    StringBuilder tmp = new StringBuilder();
    for(double d : values) {
        tmp.append(d);
        tmp.append("\n");
    }
    return tmp.toString();
}
}

person Community    schedule 12.10.2014    source источник


Ответы (2)


e.printStackTrace печатает сообщения на стандартный вывод (System.err), тогда как весь остальной вывод идет на стандартный вывод (System.out). По умолчанию оба стандартных выходных потоков перенаправляются на одну и ту же цель (ваш терминал). Итак, ваша программа работает детерминировано, она просто выводит на два канала.

Такое поведение на самом деле хорошая идея; программа может перенаправить вывод, но по-прежнему представлять ошибки пользователям. Однако, если вы этого не хотите, вы можете распечатать ошибки на стандартный вывод с помощью

e.printStackTrace(System.out)
person phihag    schedule 12.10.2014
comment
+1. Обратите внимание, что на самом деле это отражает параллелизм: на каком-то уровне терминала запись стандартного вывода и запись стандартной ошибки происходят параллельно. - person ruakh; 13.10.2014
comment
спасибо за ответ, имеет смысл, но я бы никогда не догадался, что статы печатаются неатомарно, так как трассировка стека здесь разделена на 2 части, с другой стороны, я понятия не имею, что именно происходит при печати - person ; 13.10.2014

Существует только один поток, поэтому в вашем коде не может быть состояния гонки. Вы видите чередование потоков System.out и System.err. См., например, Вызывать исключения во время выполнения правильно упорядочен с помощью println в выводе консоли

person assylias    schedule 12.10.2014