Получение Муравья <javac> для распознавания пути к классу

Оператор stop = true; не является операцией «чтение-запись», а только записью . Он вообще не читает старое значение переменной. Если предыдущее значение stop было true, утверждение не имело никакого эффекта, не заметив разницу.

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

Для вашей переменной boolean операции «чтение-изменение-запись» могут выглядеть как

if(!stop) stop = true;

или

stop = !stop;

, но для первого варианта отсутствует одновременное обновление не будет иметь большого влияния, поскольку утверждение не имеет эффекта, если переменная уже true. Второй может пропустить обновления, если они выполняются одновременно, следовательно, не отражают правильное количество операций переворачивания, но использование одновременных обновлений boolean для более чем одного перехода состояния в целом подвержено ошибкам.

Операция «чтение-запись», то есть без промежуточного «изменения / обновления», была бы операцией, которая считывает старое значение для последующего использования и записывает новое значение, не основанное на старом значении. Как

Type old = variable;
variable = newValue;
// use old here

, которые все еще будут подвержены потерянным обновлениям, если не будут сделаны атомарно. Таким образом, такая операция также требует больше, чем переменная volative. Например. AtomicInteger.getAndSet или VarHandle.getAndSet .

Итак, расширив свой пример до

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

public class StopThread {
    private static volatile boolean stop;

    public static void main(String[] args) throws InterruptedException { 

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(!stop) {
                    System.out.println("In while...");
                }
            }
        }).start();
        for(int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1)); 
                    boolean old = stop; // broken because
                    stop = true;        // not atomic
                    System.out.println(old? "other thread was faster": "sent stop signal");
                }
            }).start();
        }
    }
}

, несколько потоков могут подумать, что они отправили сигнал остановки.

Если вы исправите код на

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;

public class StopThread {
    private static final AtomicBoolean stop = new AtomicBoolean();

    public static void main(String[] args) throws InterruptedException { 

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(!stop.get()) {
                    System.out.println("In while...");
                }
            }
        }).start();
        for(int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1)); 
                    boolean old = stop.getAndSet(true);
                    System.out.println(old? "other thread was faster": "sent stop signal");
                }
            }).start();
        }
    }
}

, то только один поток возьмет на себя ответственность за отправку сигнала остановки.

42
задан Paul Fisher 6 April 2009 в 19:18
поделиться

3 ответа

Вот пример из проекта, я в настоящее время продолжаю работать. Я подозреваю, что можно изменить его для работы на ситуацию.

<path id="master-classpath">
  <fileset dir="${web.dir}/WEB-INF/lib">
    <include name="*.jar"/>
  </fileset>

  <fileset dir="${appserver.lib}">
    <include name="servlet*.jar"/>
  </fileset>

  <pathelement path="${build.dir}"/>
</path>

...

<javac destdir="${build.dir}">
  <src path="${src.dir}"/>
  <classpath refid="master-classpath"/>
</javac>
70
ответ дан William Brendel 26 November 2019 в 23:32
поделиться

Попробовать

<javac ... classpathref="TSA.classpath">

или

<javac ...>
    ...
    <classpath refid="TSA.classpath" />
</javac>
15
ответ дан Joachim Sauer 26 November 2019 в 23:32
поделиться

Попробуйте это:

 <classpath refid="TSA.classpath"/>
14
ответ дан TofuBeer 26 November 2019 в 23:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: