Spec-Zone .ru
спецификации, руководства, описания, API
|
Этот документ обсуждает, как виртуальная машина Java (JVM) отображает приоритеты для потоков, выполняющихся в JVM (потоки Java) на собственные приоритеты потока на Солярисе. Это покрывает и ток и прошлые реализации потоков Соляриса и JVM.
JVM определяет диапазон десяти логических приоритетов для потоков Java, включая:
java.lang.Thread.MIN_PRIORITY = 1 java.lang.Thread.NORM_PRIORITY = 5 java.lang.Thread.MAX_PRIORITY = 10
Эти значения [1.. В 10] передают Thread.setPriority(int)
присваивать приоритеты потокам Java. Приоритет значения по умолчанию потока Java NORM_PRIORITY
. (Поток Java, который явно не вызывает setPriority
выполнения в NORM_PRIORITY
.) JVM свободна реализовать приоритеты всегда, она выбирает, включая игнорирование значения.
Java виртуальная машина HotSpot в настоящий момент связывает каждый поток Java с уникальным собственным потоком. Отношение между потоком Java и собственным потоком устойчиво и сохраняется для времени жизни потока Java.
До Соляриса 9 значение по умолчанию libthread было так называемым T1 libthread. T1, обеспеченный модель потоков M:N, где М. собственных потоков были мультиплексированы сверху потоков ядра N (LWPs). Отношение между собственными потоками и LWPs было жидким и динамичным и могло измениться даже, в то время как поток работал и без знания потока. Солярис, обеспеченный priocntl()
системный вызов, чтобы изменить диспетчерский приоритет LWP, но потому что отношение между LWPs и собственными потоками было нестабильным, таким образом, не был никаким надежным способом измениться, чтобы изменить диспетчерский приоритет собственного потока. (JVM могла изменить приоритет LWP, на котором поток Java был в настоящий момент рабочим, но поток мог переключиться на другой LWP без знания JVM).
T2, значение по умолчанию libthread в Солярисе 9 и лучше, реализует намного более простое и устойчивое 1:1 модель потоков. Каждый собственный поток присваивается уникальному LWP, и то отношение устойчиво для времени жизни собственного потока.
И T1 и T2 представляют a thr_setprio()
API, что использование приложений, чтобы установить локальный для процесса приоритет потока. Значение, присвоенное thr_setprio()
локальный для процесса атрибут и не видим к планировщику ядра. thr_setprio()
- управление приоритетами размещение и упорядочивание потоков на локальных для процесса очередях сна на уровне пользователя, таких как очередь потоков связались с локальным для процесса взаимным исключением, с которым спорят. В HotSpot неспорят с большинством взаимных исключений, и condvars имеют, обычно имеют или 0 или 1 поток. Также, упорядочивание, наложенное thr_setprio()
- приоритет имеет очень немного эффекта на большинство потоков Java. thr_setprio()
функция поддерживает приоритетные значения в диапазоне 0 до 127, включительно, с 127 представлениями самого высокого приоритета.
T1 также использует приоритет потока реализовать элементарное вытеснение непривилегированного режима. T1 поддерживает инвариант что thr_setprio()
- приоритет любого потока на локальной готовой очереди должен быть меньше чем или равным приоритету любого несвязанного потока, это является в настоящий момент рабочим и связанным с LWP. Если инварианту угрожают, T1 вытесняет самый низкий приоритетный поток выполнения, чтобы "украсть" его LWP, чтобы восстановить инвариант.
Вытеснение может произойти в этих случаях:
Ранняя версия T2, называемого альтернативой libthread, появилась в Солярисе 8.
Для дополнительной информации о T1 T2, и LWPs обращаются к следующему:
В Солярисе приоритет LWP влияет, сколько циклически повторяет ЦП, поток получает относительно других потоков. Планировщик Соляриса использует приоритет (среди других факторов), чтобы определить, должен ли один поток вытеснить другой поток, как часто поток работает, и сколько времени поток работает. Собственные приоритеты LWP присваиваются priocntl()
системный вызов.
Чтобы резюмировать, у нас есть потоки Java с приоритетами, установленными Thread.setPriority
метод. Потоки Java работают на собственных потоках. thr_setprio()
функция используется, чтобы изменить приоритет собственных потоков. Собственные потоки, на которых работают LWPs. priocntl()
системный вызов используется, чтобы изменить приоритет LWPs.
В выпусках ранее чем 1.4.2, когда поток Java, вызванный Thread.setPriority
метод или когда поток создавался, HotSpot, вызовет thr_setprio()
отобразить приоритет Java на собственный приоритет. Вызов thr_setprio()
имеемый очень небольшой эффект на поведение при выполнении потока Java. JVM не вызывала priocntl()
скорректировать приоритет базового LWP. Это было сознательным проектным решением, потому что в 1.4.2 периода времени единственным libthread доступным на Солярисе был более старый T1 libthread.
Отметьте: JVM, возможно, вынудила собственные потоки быть связанными 1:1 с LWPs под T1, определяя THR_BOUND
когда потоки создаются. THR_BOUND
не достаточно, однако, поскольку потоки, которые присоединяют к JVM, не могли бы быть THR_BOUND
и исконный поток не THR_BOUND
., Учитывая, что нет никакого пути в Солярисе, чтобы вынудить поток быть связанным после того, как он был создан, конструкторы HotSpot, решенные, что было благоразумно не изменить приоритет LWP когда вызванный поток Java setPriority()
В 1.4.2 HotSpot смог определить во время запуска, если оно работало под T1 или T2. Если бы JVM, запущенная под T1 эффект приоритетов, была бы точно тем же самым как в более ранних выпусках.
Под T2, однако, 1.4.2 преобразованных звонка Thread.setPriority
метод в звонки в обоих thr_setprio()
(чтобы изменить собственный локальный для процесса приоритет) и к priocntl()
(чтобы изменить диспетчерский приоритет базового LWP). JVM вызывают priocntl()
только для потоков, которые работают в TS (доля времени), (интерактивный) IA, и RT классы планирования (в реальном времени). Сошлитесь на Солярис priocntl(2)
страница справочника для описания планирования классов. Если бы поток Java не был в TS, IA, или классах планирования RT, то JVM не попыталась бы установить приоритет базового LWP с priocntl()
.
К сожалению, приоритет значения по умолчанию собственных потоков в TS и IA планирование классов является максимально возможным приоритетом. Значение по умолчанию логический приоритет для потоков Java NORM_PRIORITY
, который находится на полпути в домене приоритетов потока Java. Когда JVM отображается NORM_PRIORITY
к собственным и приоритетам LWP результатом является значение, которое является менее тогда значением по умолчанию собственный приоритет. Скажем, у нас есть система с 2 ЦП, выполняющая JVM, и у той JVM есть два потока Java, оба в NORM_PRIORITY
. Предположите, что потоки находятся в IA или TS планирование class, как обычно имеет место. Когда потоки Java создаются, вызовы JVM priocntl()
отображаться NORM_PRIORITY
к середине TS или приоритетных полос IA. Кроме того предположите, что 2 собственных потока "C" в другом процессе выполняют/подготавливают одновременно с потоками Java. И собственные потоки C и потоки Java ограничены ЦП и вращение, вычисляя. Собственные потоки выполнят в самом высоком приоритете в TS или IA планирование class, и потоки JVM будут работать в среднем приоритете. Так как все четыре потока конкурируют за циклы ЦП, собственные потоки получат относительно больше циклов ЦП, и потоки Java будут, в некотором смысле, ставиться в невыгодное положение. Этот эффект происходит только, когда потоки Java конкурируют с нормальными потоками, и система полностью насыщается.
Наоборот, преимущество использования более низких относительных приоритетов - то, что в TS и IA планирование классов поток, работающий в более низких приоритетах, получает более длинный квант, предполагая, что это не вытеснило середину кванта более высокими приоритетными потоками, которые становятся готовыми. Более длинный квант часто выгоден для потоков в серверных приложениях как уровень контекстного переключения от уменьшений вытеснения. Потоку разрешают работать на ЦП в течение более длительного периода и переходного процесса перезагрузки кэша (период сразу после того, как поток планируется на ЦП: то, когда поток подвергается высокому уровню неудачного обращения в кэш, поскольку он повторно заполняет кэши данных ЦП и перемещает данные предыдущего сообщения), амортизируется по более длинному кванту.
JRE 5.0 обеспечивает тот же самый приоритет, отображающийся как 1.4.2 за исключением того, что приоритеты Java в диапазоне [10... 5] все отображаются на максимально возможный TS или приоритет IA, в то время как приоритеты в диапазоне [1.. 4] отображаются, чтобы соответственно понизить собственный TS или приоритеты IA. Преимущество этого изменения является тем Java потоки в NORM_PRIORITY
может теперь конкурировать как ожидалось с собственными потоками. Если ни потоки Java, ни собственные потоки явно не установили приоритеты (который обычно имеет место), оба класса потока конкурируют на равной опоре, работающей в самом высоком приоритете в TS или IA планирование class.
Принятие, что потоки Java явно не устанавливают свой приоритет с setPriority()
, это изменение восстанавливает поведение и эффективный приоритет LWP потоков Java, который использовался до 1.4.2. Недостаток к этой реализации - то, что приоритеты Java от 5 до 10 не дифференцируются. Поток Java в логическом приоритете 8 карт к тому же самому приоритету LWP как поток Java в приоритете 9, например.
Следующие операторы применяются ко всем версиям HotSpot:
Thread.setPriority
метод может быть дорогой работой. Фривольные приоритетные корректировки могут уменьшить производительность.NORM_PRIORITY
. Это, поочередно, изменяет собственный приоритет потока и потенциально изменяет приоритет LWP, на котором работает собственный поток. Определенно, если собственный поток корректирует свой приоритет и затем присоединяет к JVM, JVM перезаписывает предыдущие приоритетные настройки потока. JVM не "отменяет" или восстанавливает приоритет собственного потока, если поток отсоединяется. Thread.setPriority
и Thread.yield
методы являются консультацией. Они составляют подсказки от приложения до JVM. Должным образом записанный, устойчивый, независимый от платформы код может использовать setPriority()
и yield()
оптимизировать производительность приложения, но не должно зависеть от этих атрибутов для правильности. Аналогично, никакие предположения не должны быть сделаны о порядке, в котором потокам предоставляют владение монитора или порядка, в котором потоки просыпаются в ответ на notify
или notifyAll
метод. Превосходной ссылкой для этих тем является Глава 9, "Потоки", в книге Джошуа Блоха