• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

Основы Синхронизации Потоков

Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155
Основы синхронизации.

Содержание:
  • Как разделять данные между потоками?
  • Атомарность при доступе к общим данным.
  • Дополнительные проблемы с VCL.
  • Многопроцессорные машины.
  • Решение для Delphi: TThread.Synchronize.
  • Как это работает? Что делает Synchronize?
  • Синхронизация для не-VCL потоков.

Как разделять данные между потоками?

Прежде всего, необходимо знать, что для каждого процесса и потока сохраняется его состояние. У всякого потока имеется собственный программный счетчик и состояние процессора. Это означает, что код каждого потока исполняется независимо. Каждый поток обладает также своим стеком, так что локальные переменные в сущности видны лишь внутри каждого отдельного потока, и для этих переменных не существует вопросов синхронизации . Глобальные же данные программы могут быть общими для нескольких потоков, и для них, таким образом, может появиться проблема синхронизации. Конечно, это не страшно, если переменная глобальна, но используется только одним потоком. Такая же ситуация и для для памяти, распределенной в куче (обычно для объектов): в принципе, любой поток может иметь доступ к конкретному объекту, но если программа написана так, чтобы только у одного потока был указатель на конкретный объект, то только он и может обращаться к этому объекту, и проблемы синхронизации не возникает.
В Delphi есть зарезервированное слово threadvar, что позволяет объявлять "глобальные" переменные, копия которых создается для каждого потока. Эта возможность используется нечасто, поскольку обычно удобнее размещать такие переменные в классе TThread, создавая, таким образом, один экземпляр переменной для каждого созданного потомка TThread.

Атомарность при доступе к общим данным.

Для того, чтобы понять, как заставить потоки работать вместе, необходимо понимать концепцию атомарности. Действие или последовательность действий называются атомарными, если они неделимы. Когда поток выполняет атомарное действие, то все другие потоки видят это действие или как еще не начатое, или как уже завершенное. Невозможно одному потоку застать другой "в действии". Если потоки несинхронизированы, то все действия неатомарные. Давайте рассмотрим простой пример:

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



Когда вызывается Synchronize, рабочий поток приостанавливается. На этой стадии основной поток VCL может быть приостановлен в состоянии ожидания (idle), может быть временно приостановлен для операций ввода-вывода, а может и выполняться. Рабочий поток ждет, пока главный не перейдет в состояние ожидания (цикл обработки сообщений). Как только основной поток приостановится, метод без параметров, переданный в Synchronize, выполняется в контексте основного потока VCL . В нашем случае метод без параметров называется UpdateResults и работает он c Memo. Это гарантирует, что никаких конфликтов с основным потоком VCL не произойдет, и в сущности, выполнение этого кода очень похоже на выполнение любого кода Delphi, который срабатывает в ответ на сообщение, посланное приложению. Никаких конфликтов с потоком, вызвавшим Synchronize, не происходит, поскольку он приостановлен в известной безопасной точке (в коде TThread.Synchronize).
Когда это "выполнение кода по доверенности" завершается, основной поток VCL снова свободно может исполнять свои прямые обязанности, а поток, вызвавший Synchronize, продолжает свою работу после возврата из вызова. Таким образом, вызов Synchronize в основном потоке VCL выглядит подобно обработке сообщения, а в счетном потоке - как вызов функции. Код потоков находится в известных точках, и конкуренции нет. Конфликты исключены. Проблема решена.

Синхронизация для не-VCL потоков.

Мой предыдущий пример показывает, как можно создать дополнительный поток, взаимодействующий с основным потоком VCL. Для этого он заимствует время основного потока VCL. Но такой подход не сработает при взаимодействии нескольких дополнительных потоков между собой. Если у вас есть два не-VCL потока, X и Y, то вы не можете вызвать Synchronize в одном лишь потоке X, и при этом модифицировать данные, хранимые в Y. Необходимо вызывать Synchronize из обои х потоков при чтении или записи разделяемых данных. На деле это означает, что данные модифицируются основным потоком VCL, а все другие потоки синхронизируются с основным каждый раз, когда им нужен доступ к этим данным. Это выполнимо, но неэффективно, особенно если основной поток занят: каждый раз, когда двум потокам нужно связаться, они должны ждать, пока третий не перейдет в режим ожидания. Позже мы увидим, как следует управлять параллельным выполнением потоков и их прямым взаимодействием.
 
K Оффлайн

Kolovrat

Принятый Кодер
Регистрация
10 Апр 2016
Сообщения
38
Баллы
50
у меня вопрос где правильно выставляется это метод?я смотрю многие ставят его его в самом конце основного потока,а у меня так не работает,работает только допустим если сразу после каждого результата где нужна синхронизация и приходится в одном экзекьюте не один раз синхронизировать данные,я наверно не правильно делаю?насколько я знаю чем больше синхронизаций тем меньше скорость
 
Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155
У меня все нормально работает использую всегда в конце,дай пример твой посмотрю. Смотря как напишешь синхронизацию и с чего начнется твой поток так же влияют очень сильно приоритеты .
 
S Оффлайн

Shrila

Принятый Кодер
Регистрация
7 Дек 2016
Сообщения
21
Баллы
30
А что в данном случае подразумевается под синхронизацией потоков? Использование какого-нибудь общего ресурса?
 
Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155
Для того, чтобы реализовать многозадачность
 
S Оффлайн

Shrila

Принятый Кодер
Регистрация
7 Дек 2016
Сообщения
21
Баллы
30
Спасибо за пояснение. Я использую Synchronize вызов при работе с Indy компонентом TIdTCPClient.
 
Вверх Снизу