Этот вопрос задавали Анджеле в предыдущем интервью. Он появился после предыдущей статьи, чтобы представить переключение между режимом пользователя и режимом ядра, когда вызов потока завершен. Позже я расскажу о параллельном Java.
Интервьюер: Я слышал от предыдущего интервьюера, что вы хорошо разбираетесь в параллелизме Java, давайте обсудим всесторонне;
Я: Глядя на редкую соединительную ткань в голове интервьюера, я уже почувствовал, что это интервью было непростым, но, к счастью, заранее прочитав блог Анжелы и подготовившись, я ответил: Кашель, я осилил Все нормально.
Интервьюер: Вы когда-нибудь использовали потоки Java?
я: использовал.
Интервьюер: Тогда расскажите мне о потоках Java и операционных системах?
меня! ! !
Сюжет не должен быть таким, открытие не должно быть синхронизированным или volatile, а потом пул потоков и AQS.
Я: Хорошо, тогда я разобью это на три абзаца,
- Поток пользовательского режима
- поток ядра
- Исходный код потока Java
1. Поток пользовательского режима
Первый этап:
На самом деле, в первые дни в операционной системе не было концепции потоков. Потоки были добавлены позже. В начале операционной системы были только процессы. Наименьшей единицей ресурсов, выделяемых операционной системой, был процесс Процессы были изолированы друг от друга.Каждый процесс имеет собственное пространство памяти, файловый дескриптор и планировщик процессора.
вторая стадия:
На заре многопоточности потоки реализовывались в пользовательском пространстве.
В чем смысл? Все мы знаем, что память делится на пространство пользователя и системное пространство.Системное пространство используется операционной системой, а пользовательское пространство используется приложением.Если приложению требуется доступ к системному пространству, ему необходимо создать системное пространство. вызов для переключения из пользовательского режима в режим ядра.Здесь Подробнее см. в моей предыдущей статье: [Разговор о пользовательском пространстве и пространстве ядра]
Вот как это реализовано в пространстве пользователя MultiPhreading?
На самом деле операционная система выполняет планирование в соответствии с измерением процесса.Операционная система не заботится о переключении ваших пользовательских потоков.Прикладная программа создает, поддерживает и планирует потоки в пользовательском пространстве. Модель выглядит следующим образом:
Когда потоки реализуются в пользовательском пространстве, операционная система ничего не знает о существовании потоков и может видеть только процесс, а не поток. Все потоки реализованы в пользовательском пространстве. С точки зрения операционной системы каждый процесс имеет только один поток.
Одним из преимуществ такого подхода является то, что даже если операционная система не поддерживает потоки, это может поддерживаться библиотечными функциями. В JDK1.1 вместо исходного потока используется зеленый поток.
Ниже приводится объяснение зеленой нити, потому что зеленая нить сегодня не в центре внимания, поэтому я не буду вдаваться в подробности.
green threadsПоток, запланированный средой выполнения или виртуальной машиной (ВМ), а не собственной базовой операционной системой. Зеленые потоки не зависят от базовых системных функций и имитируют работу многопоточности.Управление и развертывание таких потоков происходит в пространстве пользователя, а не в пространстве ядра, поэтому они могут работать в средах без поддержки собственных потоков. В Java 1.1 зеленые потоки (по крайней мере, в Solaris) были единственной моделью потоков, используемой в JVM. Поскольку зеленые потоки имеют некоторые ограничения в использовании по сравнению с собственными потоками, последующие версии Java отказались от зеленых потоков в пользу использованияnative threads.
Преимущества и недостатки этого режима очевидны:
Недостатки: Поскольку операционная система не знает о существовании потоков, переключение временных интервалов ЦП основано на процессе.Если поток в процессе выполняет какие-либо трудоемкие операции, весь процесс будет заблокирован. Кроме того, когда поток (зеленый поток) в процессе выполняет системный вызов, такой как сетевой ввод-вывод, прерывание по ошибке страницы и т. д., и поток блокируется, операционная система блокирует весь процесс, даже если другие потоки в процесс все еще работает.
Преимущества: Использование библиотечных функций для реализации переключения потоков избавляет от необходимости переключаться из пользовательского режима в режим ядра.Этот вкус непривычен.Кстати, сопрограммы Go частично позаимствовали эту идею.
2. Потоки режима ядра
После Java 1.2 JVM в Linux основана наpthread
Можно прямо сказать, что потоки Java реализуются операционной системой, что представляет собой отношение 1:1.
Суть текущего Java-потока на самом деле является потоком в операционной системе.
Кроме того, я видел много информации о том, что реализация потоков Java - это LWP (облегченный процесс). Фактически, начиная с ядра Linux 2.6, LinuxThread был заменен новым методом реализации потоков NPTL. NPTL решает подавляющее большинство LinuxThread , Большинство функций несовместимы со стандартом POSIX и обеспечивают лучшую производительность, масштабируемость, ремонтопригодность и т. д.
LinuxThread использует модель 1*1, то есть каждый поток пользовательского режима имеет соответствующий ему объект управления ядром, а объект управления, соответствующий этому ядру, является процессом, также известным как LWP (облегченный процесс).
Если вы хотите узнать больше о NPTL, вы можете перейти к подробному введениюNPTL.
Мы знаем, что каждый поток имеет свой собственный контекст потока, который включает в себя набор идентификаторов потоков, стеков, программных счетчиков, регистров общего назначения и так далее. Мне всегда кажется, что слово «контекст» неоднозначно, но я не могу найти более подходящего слова для его описания.
Потоки имеют свой собственный независимый контекст и планируются операционной системой, но есть и недостаток, заключающийся в том, что потоки потребляют слишком много ресурсов. создавать десятки тысяч потоков на одной машине. Так позже на уровне языков программирования появилась такая штука, как сопрограммы.
Режим сопрограммы подобен комбинации двух вышеупомянутых методов, то есть переключению ресурсов потока в пользовательском режиме и планированию потока на уровне ядра операционной системой.
Между сопрограммами и потоками операционной системы существует отношение отображения. Например, мы построили m сопрограмм, которые должны выполняться в N потоках. Это схема m:n. Эти n потоков также реализуются операционной системой. планирование.
Кроме того, сопрограммы используют стековую память по запросу, поэтому теоретически можно легко создать миллионы сопрограмм.
В настоящее время лучше всего поддерживается сопрограмма языка go, но теперь сообщество OpenJDK также добавляет поддержку сопрограмм в JDK.
3. Исходный код потока
Мы звоним на Javanew Thread(Runnable ***).start()
метод, как переключиться из пользовательского режима в режим ядра, отправить системные вызовы и создать поток на уровне ядра операционной системы?
Это можно детализировать шаг за шагом. Адрес исходного кода будет вставлен в конце статьи. Здесь будут вставлены только начало и конец. Ключевым моментом является исходный код системного вызова уровня JVM для создания потока. .
Первый — нативный метод:private native void start0();
Рядом с файлом Thread.c:
Строка 44, метод отображения; погоня переходит к JVM_StartThreadjvm.cpp
В системе Linux см.src/hotspot/os/linux/os_linux.cpp
Основное внимание уделяется pthread_create. Здесь нужно завершить системный вызов с помощью библиотечной функции linux c и переключиться из пользовательского режима в режим ядра для завершения создания потоков.
Адрес исходного кода в тексте:
Наконец, боюсь ввести всех в заблуждение, говоря, что волосы не относятся к соединительной ткани.
Пользователи сети любят говорить о стрижках так: завтра у меня операция, и у меня будет групповой разрез соединительной ткани в голове, желаю удачи!
Ссылаться на: