Читаем Linux API. Исчерпывающее руководство полностью

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

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

Потоки создаются с помощью функции pthread_create(). Любой поток может завершиться независимо от других, используя функцию pthread_exit() (если вызвать exit() в любом из потоков, все они будут немедленно завершены). Если поток не был помечен как отсоединенный (например, с помощью вызова pthread_detach()), он должен быть присоединен другим потоком посредством функции pthread_join(), которая возвращает код завершения присоединенного потока.


Дополнительная информация

[Butenhof, 1996] содержит понятное и в то же время глубокое описание библиотеки Pthreads. Эта библиотека также хорошо освещена в [Robbins & Robbins, 2003]. [Tanenbaum, 2007] предоставляет теоретическое введение в понятие потоков, рассматривая такие темы, как мьютексы, критические регионы, условные переменные, а также обнаружение и обход взаимного блокирования. [Vahalia, 1996] содержит общие сведения о реализации потоков.


29.11. Упражнения


29.1. К каким возможным последствиям может привести выполнение потоком следующего кода?

pthread_join(pthread_self(), NULL);

Напишите программу, чтобы увидеть, что же в действительности происходит в системе Linux. Представьте, что у нас есть переменная tid, содержащая идентификатор потока; каким образом поток может избежать выполнения вызова pthread_join(tid, NULL), являющегося эквивалентом вышеприведенной операции?

29.2. Что не так со следующей программой, если не брать во внимание отсутствие проверок на ошибки и объявлений различных переменных и структур?

static void *

threadFunc(void *arg)

{

struct someStruct *pbuf = (struct someStruct *) arg;


/* Выполняем какие-то действия со структурой, на которую указывает 'pbuf' */

}


int

main(int argc, char *argv[])

{

struct someStruct buf;


pthread_create(&thr, NULL, threadFunc, (void *) &buf);

pthread_exit(NULL);

}

30. Потоки выполнения: синхронизация

В этой главе мы опишем два инструмента, с помощью которых потоки могут синхронизировать свои действия: мьютексы и условные переменные. Мьютексы позволяют потокам синхронизировать использование общих ресурсов, чтобы, к примеру, один поток не пытался получить доступ к разделяемой переменной в момент, когда другой поток изменяет ее значение. Условные переменные дополняют это решение, позволяя потокам оповещать друг друга о том, что разделяемая переменная (или другой общий ресурс) изменила свое состояние.


30.1. Защита доступа к разделяемым переменным: мьютексы


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

В листинге 30.1 показаны проблемы, которые могут возникнуть при неатомарном доступе к разделяемым ресурсам. Эта программа создает два потока, каждый из которых выполняет одну и ту же функцию. Функция содержит цикл, который постепенно инкрементирует глобальную переменную glob. Для этого ее значение копируется в локальную переменную loc, там же инкрементируется и копируется обратно в glob (поскольку переменная loc автоматически попадает в локальный стек потока, каждый поток имеет ее уникальную копию). Количество итераций цикла определяется аргументом командной строки, который передается программе, или значением по умолчанию, если такого аргумента не обнаружено.


Листинг 30.1. Некорректная инкрементация глобальной переменной из двух потоков

threads/thread_incr.c

#include

#include "tlpi_hdr.h"


static int glob = 0;


static void * /* 'arg' раз инкрементируем 'glob' */

threadFunc(void *arg)

{

Перейти на страницу:

Похожие книги

C++ Primer Plus
C++ Primer Plus

C++ Primer Plus is a carefully crafted, complete tutorial on one of the most significant and widely used programming languages today. An accessible and easy-to-use self-study guide, this book is appropriate for both serious students of programming as well as developers already proficient in other languages.The sixth edition of C++ Primer Plus has been updated and expanded to cover the latest developments in C++, including a detailed look at the new C++11 standard.Author and educator Stephen Prata has created an introduction to C++ that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C++ language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.Review questions and programming exercises at the end of each chapter help readers zero in on the most critical information and digest the most difficult concepts.In C++ Primer Plus, you'll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:• A new detailed chapter on the changes and additional capabilities introduced in the C++11 standard• Complete, integrated discussion of both basic C language and additional C++ features• Clear guidance about when and why to use a feature• Hands-on learning with concise and simple examples that develop your understanding a concept or two at a time• Hundreds of practical sample programs• Review questions and programming exercises at the end of each chapter to test your understanding• Coverage of generic C++ gives you the greatest possible flexibility• Teaches the ISO standard, including discussions of templates, the Standard Template Library, the string class, exceptions, RTTI, and namespaces

Стивен Прата

Программирование, программы, базы данных
1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
C# 4.0: полное руководство
C# 4.0: полное руководство

В этом полном руководстве по C# 4.0 - языку программирования, разработанному специально для среды .NET, - детально рассмотрены все основные средства языка: типы данных, операторы, управляющие операторы, классы, интерфейсы, методы, делегаты, индексаторы, события, указатели, обобщения, коллекции, основные библиотеки классов, средства многопоточного программирования и директивы препроцессора. Подробно описаны новые возможности C#, в том числе PLINQ, библиотека TPL, динамический тип данных, а также именованные и необязательные аргументы. Это справочное пособие снабжено массой полезных советов авторитетного автора и сотнями примеров программ с комментариями, благодаря которым они становятся понятными любому читателю независимо от уровня его подготовки. Книга рассчитана на широкий круг читателей, интересующихся программированием на C#.Введите сюда краткую аннотацию

Герберт Шилдт

Программирование, программы, базы данных