Что С++ 11 считает потоком?

C++11 имеет некоторое представление о потоках. Например, он определяет новый спецификатор хранилища thread_local и указывает, что для переменных с этим спецификатором хранилища «существует отдельный объект или ссылка для каждого потока» [basic.stc.thread].

Что считается "потоком" для этой цели? Это только потоки, созданные с использованием стандартной библиотеки потоков (т.е. представленные объектами std::thread)? Как насчет потоков, созданных другими способами (например, с помощью pthreads непосредственно в Linux)? Что, если я использую библиотеку, которая предоставляет потоки пользовательского пространства — каждый из них получает свои собственные копии объектов thread_local (я действительно не понимаю, как это можно реализовать)?

Если ответ «это определяется реализацией, что считается потоком для таких целей, как thread_local», может ли кто-нибудь привести пример того, как это определяет одна известная реализация?


person HighCommander4    schedule 04.11.2013    source источник
comment
@texasbruce В Java сейчас есть эти ключевые слова? Они были там 17 лет назад.   -  person user207421    schedule 04.11.2013


Ответы (3)


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

1 В следующих подпунктах описываются компоненты для создания и управления потоками (1.10), выполнения взаимного исключения и обмена условиями и значениями между потоками, как показано в таблице 148.

Ссылка на 1.10 подразумевает, что речь идет об этих темах.

1 Поток выполнения (также известный как поток) — это единый поток управления внутри программы, включая начальный...

Поэтому мне кажется, что потоки относятся только к потокам stdlib (имеется в виду std::thread и все, что библиотека поддержки потоков делает внутри). Конечно, thread_local во многих случаях может в конечном итоге работать с собственными потоками (особенно если учесть, что в конкретной системе у вас обычно нет более одного варианта реализации потоков), но, насколько я могу судить, стандарт не дает никаких гарантий.

person aaronman    schedule 04.11.2013
comment
Хотя это правда, и реализациям технически может сойти с рук поддержка thread_local только с std::thread, это будет некачественная реализация. На данный момент существующие реализации обеспечивают thread_local работу с системными потоками и std::thread обеспечивают поддержку thread_local через поддержку библиотеки системных потоков. - person bames53; 04.11.2013
comment
@ bames53 не уверен, как это относится к моему ответу, все, что я говорю, это то, что поток в С++ - это то, что реализовано внутри, std::thread, очевидно, является одним из них, но другие внутренние вещи могут создавать поток. Даже если внутри реализация использует, скажем, pthreads, и они в конечном итоге работают как поток, стандарт дает гарантию этого IMO. - person aaronman; 04.11.2013
comment
Да, я согласен с вами в том, что стандарт не гарантирует ничего, кроме std::thread. Я просто добавляю, что на практике и в известных мне реализациях thread_local будет работать с потоками системы, а не только std::thread. - person bames53; 04.11.2013
comment
@ bames53 да, скорее всего, как я уже сказал в своем редактировании, у вас не так много вариантов при реализации такого рода вещей. - person aaronman; 04.11.2013
comment
Также понятно, что main запускается в своем собственном потоке со своими собственными thread_local переменными, даже если для него нет объекта std::thread. - person MSalters; 04.11.2013
comment
1.10/1, кажется, говорит об обратном тому, что вы утверждаете. Он определяет поток как единый поток выполнения, независимо от того, почему это выполнение происходит. Он не ссылается на библиотеку. - person Potatoswatter; 05.11.2013
comment
@Potatoswatter, если у вас нет копии, отличной от моей, IT вы добавили, независимо от того, почему это выполнение происходит. В любом случае, я чувствую, что это можно интерпретировать любым из наших способов, стандарт ни в коем случае не говорит об этом однозначно, чувствую бесплатно опубликовать ответ, если вы хотите - person aaronman; 05.11.2013
comment
Какая часть моего комментария была цитатой? Все, что говорит стандарт, не относится к другим вещам, если только он не ссылается на них. Это неизменно правильный способ интерпретации. - person Potatoswatter; 05.11.2013
comment
@Potatoswatter Я думал, что некоторые из ваших комментариев по какой-то причине предназначались для цитаты. - person aaronman; 05.11.2013

C++11 §1.10/1 определяет термины:

поток выполнения (также известный как поток) – это единый поток управления внутри программы, включающий начальный вызов определенной функции верхнего уровня и рекурсивно включающий каждый вызов функции, впоследствии выполняемый потоком. [ Примечание. Когда один поток создает другой, первоначальный вызов функции верхнего уровня нового потока выполняется новым потоком, а не создающим потоком. — конец примечания ]

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

С точки зрения базового языка просто случайно, что std::thread вызывает существование такой вещи.

Что, если я использую библиотеку, которая предоставляет потоки пользовательского пространства — каждый из них получает свои собственные копии объектов thread_local (я действительно не понимаю, как это можно реализовать)?

Невозможно написать такую ​​библиотеку без вызовов ядра. По всей вероятности, все потоки в вашем процессе уже представлены высокоуровневой абстракцией, такой как pthreads, просто для удовлетворения требований ядра. Стандартная библиотека C++, скорее всего, написана против родной библиотеки потоков, чтобы «просто работать» без дополнительного клея.

Например, объекты thread_local инициализируются при первом доступе, а не при запуске каждого нового потока, поэтому компилятору просто нужно вставить запрос на основе pthread_self для доступа и, возможно, инициализации. Инициализация зарегистрирует деструктор с помощью средства pthread_cleanup.

Реализация здесь определяется тем, совместима ли уже существующая нативная библиотека с C++. Предположим, что они предоставляют это, а это то, что клиенты, как правило, хотят, все другие библиотеки потоков, созданные на его основе, будут автоматически совместимы, исключая какой-либо другой конфликт.

person Potatoswatter    schedule 05.11.2013
comment
Таким образом, чтобы на самом деле ответить на вопрос ОП, вы считаете, что все, что создает новый поток управления в программе, гарантированно будет работать с чем-то вроде thread_local по стандарту. - person aaronman; 05.11.2013

Стандарт не описывает, как ведут себя потоки, созданные другими библиотеками, и системные вызовы. Что касается стандарта, то они не определены в своем поведении. В самом С++ нет другого способа создать несколько потоков: такие библиотеки или системные вызовы делают вещи, которые не стандартизированы стандартом С++.

Теперь каждая такая библиотека и системный вызов будут вести себя так, как это определено их собственными спецификациями. Довольно часто C++ std::thread даже строится поверх таких библиотек или системных вызовов. Как именно работает взаимодействие, не уточняется.

person Yakk - Adam Nevraumont    schedule 04.11.2013