Действительно ли операторы Thread.sleep (0) и Thread.yield () эквивалентны?

Действительно ли эти два оператор эквивалентны?

Thread.sleep(0);
Thread.yield();
62
задан 21 October 2009 в 16:48

6 ответов

Нет, они не эквивалентны и помимо объяснений выше, я думаю, что необходимо проверить Javadoc yield. Это кажется не хорошей идеей использовать yield, если ниже ситуации не встречается.

 It is rarely appropriate to use this method. It may be useful
 for debugging or testing purposes, where it may help to reproduce
 bugs due to race conditions. It may also be useful when designing
 concurrency control constructs such as the ones in the
 {@link java.util.concurrent.locks} package.
0
ответ дан 31 October 2019 в 13:41

В книге известного Brian Goetz "Параллелизм Java на практике" (опубликованный в 2006, но все еще существенно допустимый) говорится следование этого вопроса.

семантика Thread.yield и Thread.sleep (0) не определена [JLS17.9]; JVM свободна реализовать их столь же без операций в секунду или рассматривать их как планирующие подсказки. В частности, они не обязаны иметь семантику сна (0) в системах Unix —, помещает текущий поток в конце очереди выполнения для того приоритета, уступая другим потокам того же приоритета —, хотя некоторые JVMs реализуют урожай таким образом.

Остальные можно найти на страницах Javadoc.

7
ответ дан 31 October 2019 в 13:41

Thread.sleep () и Thread.yield () делают то же самое за исключением того, что Thread.yield () оставляет только потокам, работающим на том же процессоре в многопроцессорной среде.

1
ответ дан 31 October 2019 в 13:41

Это - platform-and-implementation-dependent, и они вероятны не эквивалентные.

ниже отрывка, при использовании Thread.sleep (0), большую часть времени дает вывод:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

принимая во внимание, что при использовании Thread.yield (), главным образом дает:

[0, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[0, 2, 2, 2, 2, 2, 2, 2, 2, 2]

Посмотрите отрывок ниже:

public class CompareSleepZeroAndYield {
    private ArrayList<Integer> list1 = new ArrayList<>();
    private ArrayList<Integer> list2 = new ArrayList<>();

    public ArrayList<Integer> getList1() {
        return list1;
    }

    public ArrayList<Integer> getList2() {
        return list2;
    }

    public CompareSleepZeroAndYield() {
        list1.add(0);
        list2.add(0);
    }

    public void tryFieldLock1() {
        synchronized (this.list1) {
            list1.add(list2.get(list2.size() - 1) + 1);
        }
    }

    public void tryFieldLock2() {
        synchronized (this.list2) {
            list2.add(list1.get(list1.size() - 1) + 1);
        }
    }

    public static void main(String[] args) {
        CompareSleepZeroAndYield obj = new CompareSleepZeroAndYield();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                int count = 10;
                while (--count >0) {
                    obj.tryFieldLock1();
                    try {
                        Thread.sleep(0);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // compare above and below
                    // Thread.yield()
                }
                System.out.println(obj.getList1());
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                int count = 10;
                while (--count >0) {
                    obj.tryFieldLock2();

                    try {
                        Thread.sleep(0);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // compare above and below
                    // Thread.yield()
                }
                System.out.println(obj.getList2());
            }
        });
        t1.start();
        t2.start();
}
0
ответ дан 31 October 2019 в 13:41

Источник OpenJDK (Java SE 7) имеет следующую реализацию для Thread.sleep(0) в JVM_Sleep функция jvm.cpp:

  if (millis == 0) {
    // When ConvertSleepToYield is on, this matches the classic VM implementation of
    // JVM_Sleep. Critical for similar threading behaviour (Win32)
    // It appears that in certain GUI contexts, it may be beneficial to do a short sleep
    // for SOLARIS
    if (ConvertSleepToYield) {
      os::yield();
    } else {
      ThreadState old_state = thread->osthread()->get_state();
      thread->osthread()->set_state(SLEEPING);
      os::sleep(thread, MinSleepInterval, false);
      thread->osthread()->set_state(old_state);
    }
  }

И implemtation Thread.yield () имеют следующий код:

  // When ConvertYieldToSleep is off (default), this matches the classic VM use of yield.
  // Critical for similar threading behaviour
  if (ConvertYieldToSleep) {
    os::sleep(thread, MinSleepInterval, false);
  } else {
    os::yield();
  }

Так Thread.sleep(0) и Thread.yield() может назвать те же системные вызовы в некоторых платформах.

os::sleep и os::yield платформа определенный материал. И на Linux и на Windows: os::yield, кажется, много simplier, чем os::sleep. Например: os::yield из вызовов Linux только [1 113] sched_yield() . И os::sleep имеют приблизительно 70 строк кода.

13
ответ дан 31 October 2019 в 13:41

то, Что урожай (), как предполагается, делает, заставляют в настоящее время рабочий поток возвратиться к выполнимому, чтобы позволить другим потокам того же приоритета получить их очередь. Таким образом, намерение состоит в том, чтобы использовать урожай () для продвижения корректного взятия поворота среди потоков равного приоритета. В действительности, тем не менее, урожай () метод, как гарантируют, не сделает то, чего он требует, и даже если урожай () действительно заставляет поток ступать из выполнения и назад к выполнимому, нет никакой гарантии, уступающий поток будет не просто выбран снова по всему другие! Таким образом, в то время как урожай () might— и часто does— заставляет рабочий поток бросить свой слот к другому выполнимому потоку того же приоритета, нет никакой гарантии.

урожай А () никогда не будет заставлять поток переходить к waiting/sleeping/блокирующему состоянию. Самое большее урожай () заставит поток идти от выполнения до выполнимого, но снова, это не могло бы иметь никакого эффекта вообще.

Источник: SCJP Сертифицированная Sun книга

Программиста
0
ответ дан 31 October 2019 в 13:41

Другие вопросы по тегам:

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