Учебная работа. Реферат: Синхронизация потоков
Для синхронизации действий, выполняемых различными потоками существует несколько разных методов. Условно их можно поделить на последующие:
· синхронизация при помощи глобальных переменных
· синхронизация при помощи обмена событиями
· синхронизация при помощи особых объектов (событий, семафоров, критичных секций, объектов исключительного владения и остальных)
1-ый способ синхронизации следует признать самым плохим, потому что он просит неизменного опроса состояния глобальной переменной. У этого способа есть и наиболее суровые недочеты — так, к примеру, вероятна полная блокировка потоков, если поток, ожидающий конфигурации глобальной переменной имеет наиболее высочайший Ценность, чем поток, изменяющий эту переменную. правда, его можно несколько сделать лучше — вводя доп временные задержки меж поочередными опросами.
2-ой способ востребует сотворения объектов, способных получать сообщения либо уведомления о выполнении неких действий. Это могут быть окна, файлы (к примеру, при использовании асинхронных операций либо операций с извещением), сборники и т.д. В почти всех вариантах быть может комфортно сделать невидимое окно, участвующее в обмене сообщениями либо ожидающее получения сообщений для выполнения тех либо других действий.
3-ий способ — синхронизация при помощи особых объектов — востребует рассмотрения различных объектов и различных способов синхронизации с внедрением объектов. В Win32 API существует огромное число объектов, которые могут быть использованы в качестве синхронизирующих, при этом в почти всех вариантах заместо 1-го объекта может применяться объект другого типа. Потому будет любопытно разглядеть несколько главных способов синхронизации с внедрением объектов.
При рассмотрении методов синхронизации комфортно выделить несколько главных методов, используемых различными операционными системами. В числе таковых методов можно выделить четыре способа:
· критичные секции
· объекты исключительного владения
· действия
· синхронизация группой объектов
Поочередно разглядим эти главные способы, используя в качестве примера функции по работе с глобальной кучей. Попробуем абстрактно разобраться со качествами этих функций, что бы осознать, какие способы синхронизации и в которых вариантах комфортно использовать.
Во–первых, глобальную кучу в целом можно разглядывать как некоторый непростой объект, над которым могут производиться некие операции (пока мы рассматриваем лишь операции над кучей в целом, не вдаваясь в аспекты работы с отдельными блоками — по мере необходимости доступ к отдельным блокам кучи должен быть синхронизирован, но это уже не функции кучи, а неувязка того, кто пользуется кучей).
часть операций, к примеру получение указателя на какой–или блок в куче, не нуждается в изменении самой кучи. Другими словами функции, осуществляющие подобные операции могут производиться сразу различными потоками не конфликтуя друг с другом. Такие функции комфортно именовать “читателями” — они не изменяют кучу как единый объект.
Остальные операции, к примеру выделение новейшего блока в куче, требуют внесения конфигураций в кучу — конфигурации в цепочке выделяемых блоков. Обычно такие конфигурации осуществляются не в одном месте, а требуется согласованное внесение конфигураций в нескольких структурах данных. В процессе таковой операции структура кучи какое–то время оказывается нарушенной, вследствие что одновременное выполнение таковых действий обязано быть исключено. Такие функции комфортно именовать “писателями” — они изменяют кучу как единый объект.
Применительно к куче вероятен одновременный доступ нескольких читателей и исключительный — писателей. Наиболее того, если к куче получает доступ писатель, то читатели также должны быть лишены доступа (в остальных вариантах это быть может не так — читатели могут работать сразу с писателем).
Можно сконструировать несколько правил для работы с таковым объектом:
· если к объекту имеет доступ писатель, то ни читатели, ни остальные писатели доступа не имеют;
· если к объекту имеет доступ читатель, то вероятен одновременный доступ остальных читателей и запрещен доступ писателям;
· если объект волен, то 1-ый пришедший писатель либо читатель имеет Право доступа.
Рассмотренный пример весьма комфортен, потому что схожая ситуация (много читателей, единственный писатель) встречается сплошь и — а обычного объекта для синхронизации доступа к такому объекту нет. Благодаря этому таковой пример становится благодатной почвой для рассмотрения различных методов синхронизации.
Номер
Поток, уже имеющий доступ
Поток, требующий доступа
действие
1
читатель
читатель
разрешить доступ
2
читатель
писатель
ждать освобождения[1]
3
писатель
читатель
ждать освобождения[1]
4
писатель
писатель
ждать освобождения
5
—
читатель
разрешить доступ
6
—
писатель
разрешить доступ
Даже при простом анализе таковой таблицы можно увидеть, что писатели находятся в неравном положении — при довольно большенном числе читателей и писателей вероятна полная блокировка крайних, потому что читатели могут получать Право одновременного доступа к объекту, так что вероятна ситуация, когда объект совершенно не будет освобожден для писателей — хоть один читатель да найдется. Для выхода из таковой ситуации следует слегка видоизменять реакцию объекта во 1м случае — если имеется ожидающий поток–писатель, то нужно разрешить доступ ему, а не читателю. Для полной “симметрии” следует в 4м случае инспектировать наличие читателей и разрешать им доступ, даже если имеется ожидающий поток–писатель. Таковой механизм, хотя и довольно непростой в реализации, обеспечит наиболее–наименее равные права для выполнения потоков различного типа.
Этот синхронизирующий объект может употребляться лишь локально снутри процесса, создавшего его. Другие объекты могут быть применены для синхронизации потоков различных действий. Заглавие объекта “критичная секция” соединено с неким абстрактным выделением части программного кода (секции), выполняющего некие операции, порядок которых не быть может нарушен. Другими словами попытка 2-мя различными потоками сразу делать код данной секции приведет к ошибке.
к примеру, таковой секцией быть может комфортно защитить функции–писатели, потому что одновременный доступ нескольких писателей должен быть исключен.
Для критичной секции вводят две операции:
· войти в секцию;
Пока какой–или поток находится в критичной секции, все другие потоки при попытке войти в нее будут автоматом останавливаться в ожидании. Поток, уже вошедший в эту секцию, может заходить в нее неоднократно, не ждя ее освобождения.
· покинуть секцию;
При покидании потоком секции миниатюризируется счетчик числа вхождений этого потока в секцию, так что секция будет освобождена для остальных потоков лишь если поток выйдет из секции столько раз, сколько раз в нее заходил. При освобождении критичной секции будет пробужден лишь один поток, ожидающий разрешения на вход в эту секцию.
Совершенно говоря, в остальных API, хороших от Win32 (к примеру, OS/2), критичная секция рассматривается не как синхронизирующий объект, как фрагмент кода программки, который может исполняться лишь одним потоком приложения. Другими словами вход в критичную секцию рассматривается как временное выключение механизма переключения потоков до выхода из данной секции. В Win32 API критичные секции рассматриваются как объекты, что приводит к определенной неурядице — они весьма близки по своим свойствам к неименованным объектам исключительного владения (mutex, см. ниже).
При использовании критичных секций нужно смотреть, что бы в секции не выделялись очень огромные фрагменты кода, потому что это может привести к значимым задержкам в выполнении остальных потоков.
к примеру, применительно к уже рассмотренным кучам — не имеет смысла все функции по работе с кучей защищать критичной секцией, потому что функции–читатели могут производиться параллельно. Наиболее того, применение критичной секции даже для синхронизации писателей по сути представляется малоудобным — потому что для синхронизации писателя с читателями крайним все–равно придется заходить в эту секцию, что фактически приводит к защите всех функций единой секцией.
Можно выделить несколько случаев действенного внедрения критичных секций:
· читатели не конфликтуют с писателями (защищать нужно лишь писателей);
· все потоки имеют приблизительно равные права доступа (скажем, недозволено выделить незапятнанных писателей и читателей);
· при построении составных синхронизирующих объектов, состоящих из нескольких обычных, для защиты поочередных операций над составным объектом.
Объекты исключительного владения — mutex (mut
ualex
clusion) — могут принадлежать лишь одному сгустку сразу. Соответственно определяются операции над этими объектами:
· затребовать владение объектом;
При запросе владения система инспектирует, обладает–ли какой–или иной поток сиим объектом либо нет. Если имеется иной поток–обладатель, то данный поток останавливается до того времени, пока объект не освободиться. Как объект становится вольным, система дает его во владение новенькому сгустку. Поток, уже обладающий объектом, может неоднократно вступать во владение им.
· высвободить объект;
При освобождении объекта система просматривает, имеются–ли остальные потоки, ожидающие освобождения этого объекта. Если имеются, то возобновит работу лишь один поток, а все другие продолжат ожидание — объект mutex быть может во владении лишь у 1-го потока. Освобождать объект может лишь тот поток, который им в данный момент обладает, остальные потоки этого создать не могут. Для полного освобождения объекта поток должен столько раз высвободить его, сколько раз он затребовал владение с того момента, как ему дали этот объект во владение.
Если учитывать, что обладать объектом mutex может лишь один поток, то выходит, что такие объекты похожи на критичные секции — с того момента, как система дала объект во владение сгустку все другие, которые захочут получить его во владение, будут ждать его освобождения. Отличия заключаются в неких аспектах использования — во–первых, объекты mutex могут быть применены различными действиями (для этого предусмотрены именованные объекты, которые могут быть применены иными действиями) и, во–вторых, ждать владения сиим объектом можно различными методами — с ограничением по времени либо, к примеру, применять его для синхронизации сходу с несколькими объектами (иными объектами mutex, семафорами, событиями и иным). О этом — подробнее в следующих разделах.
Действия, как и объекты исключительного владения, могут употребляться для синхронизации потоков, принадлежащих различным приложениям. Самые значимые отличия сводятся к последующему:
· событиями никто не обладает — другими словами устанавливать действия в свободное либо занятое состояние могут любые потоки, имеющие право доступа к этому объекту
· действия различают лишь два состояния — свободное и занятое. сколько бы раз вы не переводили событие в занятое состояние, один единственный вызов функции, освобождающей это событие, высвободит его. И напротив.
· в традиционном варианте освобождение действия разрешает пуск всех потоков, ожидающих его. Объекты исключительного владения и критичные секции дозволяли возобновить выполнение лишь 1-го потока[2]
.
· смена состояния действия осуществляется в хоть какой момент времени. Так, для вхождения в критичную секцию либо для получения объекта mutex во владение нужно было дождаться их освобождения (что производилось автоматом). Для событий это не так.
Соответственно, применительно к событиям, молвят о 2-ух главных состояниях: вольном (установленном) и занятом (сброшенном) и о 3-х операциях, выполняемых над ними:
· сбросить событие;
Событие в сброшенном состоянии считается занятым. цвета). Опущенный флаг (либо выключенная лампа) означают, что такси занято. Хоть какой поток, имеющий доступ к событию, может сбросить его, независимо от того, какой поток это событие устанавливал.
· установить (время от времени — отправить) событие;
Установленное (посланное) событие считается вольным. Как событие освобождается, все ожидающие его потоки могут возобновить свое выполнение (см. сноску). Устанавливать событие может также хоть какой поток.
· дождаться действия;
Потому что сброс и установка событий происходит в хоть какой момент времени, независимо от предшествующего состояния действия, то приходится вводить специальную операцию — дождаться освобождения объекта.
Эти индивидуальности выделяют действия в необыкновенную категорию синхронизирующих объектов. Рассмотренные ранее критичные секции и объекты исключительного владения разрешают выполнить монопольный доступ к какому–или ресурсу либо объекту данных, в то время как действия определяют некие условия, опосля которых может быть выполнение тех либо других операций.
Пример. Ворачиваясь например с глобальной кучей — для работы с ней нужно сделать составной синхронизирующий объект. Пример такового объекта можно отыскать в книжке “Windows для экспертов” Джеффри Рихтера. естественно, логика построения объекта схожа и в рассматриваемом случае, что дозволяет детально сопоставить несколько близких решений и заострить внимание на неких “мелочах”. На данный момент мы разглядим лишь “скелет” такового объекта и главные правила работы с ним. Позднее, опосля рассмотрения функций Win32 API, разглядим определенную реализацию этого составного объекта и сравним ее с очень схожим объектом, приведенным в книжке Рихтера.
Поначалу попробуем составить наличие хотя–бы 1-го читателя исключает для писателей возможность доступа к данным.
Из этих суждений следует наличие:
· Критичной секции либо объекта исключительного владения для синхронизации потоков–писателей. Выбор 1-го из этих объектов определяется необходимостью исключительного доступа лишь 1-го потока–писателя к данным. Комфортно также, что высвободить секцию либо mutex может лишь тот поток, который его занял. В рассматриваемом примере будем применять объект mutex, для большей схожести с Рихтером (это дозволит подчернуть несколько аспектов в разработке такового объекта).
· Действия, переходящего в занятое состояние при наличии хотя–бы 1-го читателя. В данном случае целенаправлено избрать событие, которое будет сбрасываться в занятое состояние при возникновении первого потока–читателя и устанавливаться в свободное крайним читателем (крайним из тех, кто пробует выполнить чтение сразу с иными, но не совершенно крайнего).
· Счетчика числа потоков–читателей, осуществляющих одновременный доступ. Нулевое состояние. При уменьшении счетчика проверяется итог — если он 0, то событие устанавливается в свободное состояние.
Можно приблизительно обрисовать структуру такового объекта (назовем его NEWSWMRG, по сопоставлению с объектом SWMRG, рассматриваемым у Рихтера — S
ingle W
riter M
ulti R
eader G
uard). Эта структура обязана быть описана приблизительно так:
struct NEWSWMRG {
СОБЫТИЕ НЕТ_ЧИТАТЕЛЕЙ;
СЧЕТЧИК ЧИСЛО_ЧИТАТЕЛЕЙ;
объект_ИСКЛЮЧИТЕЛЬНОГО_ВЛАДЕНИЯ ЕСТЬ_ПИСАТЕЛИ;
};
Для работы с ней нужно будет выделить четыре особых функции (инициализацию и удаление этого объекта пока не рассматриваем): две функции, применяемые потоками–читателями для получения доступа к данным и для обозначения конца операции чтения, также две подобных функции для потоков–писателей.
void RequestWriter( NEWSWMRG* p ) {
// дождаться разрешения для писателя
Захватить объект ЕСТЬ_ПИСАТЕЛИ;
// если объект получен во владение — остальных писателей больше нет
// и пока мы его не освободим — не покажутся.
Дождаться действия НЕТ_ЧИТАТЕЛЕЙ;
// если событие установлено — читателей также нет
}
void ReleaseWriter( NEWSWMRG* p ) {
// опосля конфигурации данных разрешаем доступ иным писателям и читателям
Высвободить объект ЕСТЬ_ПИСАТЕЛИ;
}
void RequestReader( NEWSWMRG* p ) {
// дождаться разрешения для читателя — убедиться, что нет писателей
// для этого можно захватить объект ЕСТЬ_ПИСАТЕЛИ и сходу высвободить его
// захват пройдет лишь тогда, когда писателей нет.
Захватить объект ЕСТЬ_ПИСАТЕЛИ;
// реально нужно не только лишь убедиться в отсутствии писателей, да и
// прирастить счетчик и по мере необходимости сбросить событие НЕТ_ЧИТАТЕЛЕЙ
if ( ЧИСЛО_ЧИТАТЕЛЕЙ == 0 ) Сбросить событие НЕТ_ЧИТАТЕЛЕЙ в занятое;
ЧИСЛО_ЧИТАТЕЛЕЙ++;
// а вот сейчас можно смело освобождать объект ЕСТЬ_ПИСАТЕЛИ — во время
// работы читателя довольно иметь сброшенное событие НЕТ_ЧИТАТЕЛЕЙ Высвободить объект ЕСТЬ_ПИСАТЕЛИ;
}
void ReleaseReader( NEWSWMRG* p ) {
// опосля считывания данных уменьшаем счетчик и разрешаем доступ писателям
// при достижении нулевого значения счетчика.
—ЧИСЛО_ЧИТАТЕЛЕЙ;
if ( ЧИСЛО_ЧИТАТЕЛЕЙ == 0 ) Установить событие НЕТ_ЧИТАТЕЛЕЙ в свободное;
}
естественно, это еще не рабочая схема, а лишь намек на нее. На сто процентов обсудим некие индивидуальности при рассмотрении функций Win32 API. На 1-ый взор виден маленький “прокол” — в функции ReleaseReader счетчик поначалу миниатюризируется, а лишь позже происходит проверка его значения и установка действия по мере необходимости. Но вероятен (хотя и весьма маловероятен) вариант, когда поток будет прерван для выполнения операций иными потоками где–то меж уменьшением счетчика и установкой действия. В это время остальные потоки могут поменять значение счетчика и событие будет установлено тогда, когда этого созодать уже не следует.
Выйти из данной ситуации можно различными способами — или добавлением еще 1-го объекта исключительного владения либо критичной секции для упорядочивания операций со счетчиком, или иными методами. Для разбирательства с этими другими методами следует разглядеть синхронизацию с группой объектов.
[1]
Вероятны такие объекты, хотя это не обычный вариант, когда читатели не конфликтуют с писателями. Тогда в ситуациях 2 и 3 следует разрешать доступ.
[2]
В Win32 API есть особые механизмы, дозволяющие возобновлять выполнение лишь 1-го потока при освобожении действия. Но, по сопоставлению с иными операционными системами, скажем OS/2, такое
Для синхронизации действий, выполняемых {разными|различными} потоками существует несколько {различных|разных} {способов|методов}. Условно их можно {разделить|поделить} на {следующие|последующие}:
· синхронизация {с помощью|при помощи} глобальных переменных
· синхронизация {с помощью|при помощи} обмена событиями
· синхронизация {с помощью|при помощи} {специальных|особых} объектов (событий, семафоров, {критических|критичных} секций, объектов исключительного владения и {других|остальных})
{Первый|1-ый} {метод|способ} синхронизации следует признать самым {неудачным|плохим}, {так как|потому что} он {требует|просит} {постоянного|неизменного} опроса состояния глобальной переменной. У этого {метода|способа} есть и {более|наиболее} {серьезные|суровые} {недостатки|недочеты} — так, {например|к примеру}, {возможна|вероятна} полная блокировка потоков, если поток, ожидающий {изменения|конфигурации} глобальной переменной имеет {более|наиболее} {высокий|высочайший} {приоритет|ценность}, чем поток, изменяющий эту переменную. правда, его можно несколько {улучшить|сделать лучше} — вводя {дополнительные|доп} временные задержки {между|меж} {последовательными|поочередными} опросами.
{Второй|2-ой} {метод|способ} {потребует|востребует} {создания|сотворения} объектов, способных получать сообщения {или|либо} {извещения|уведомления} о выполнении {некоторых|неких} действий. Это могут быть окна, файлы ({например|к примеру}, при использовании асинхронных операций {или|либо} операций с {уведомлением|извещением}), {каталоги|сборники} и т.д. {Во многих|В почти всех} {случаях|вариантах} {может быть|быть может} {удобно|комфортно} {создать|сделать} невидимое окно, участвующее в обмене сообщениями {или|либо} ожидающее получения сообщений для выполнения тех {или|либо} {иных|других} действий.
{Третий|3-ий} {метод|способ} — синхронизация {с помощью|при помощи} {специальных|особых} объектов — {потребует|востребует} рассмотрения {разных|различных} объектов и {разных|различных} {методов|способов} синхронизации с {использованием|внедрением} объектов. В Win32 API существует {большое|огромное} число объектов, которые могут быть {применены|использованы} в качестве синхронизирующих, {причем|при этом} {во многих|в почти всех} {случаях|вариантах} {вместо|заместо} {одного|1-го} объекта может применяться объект другого типа. {Поэтому|Потому} будет {интересно|любопытно} {рассмотреть|разглядеть} несколько {основных|главных} {методов|способов} синхронизации с {использованием|внедрением} объектов.
При рассмотрении {способов|методов} синхронизации {удобно|комфортно} выделить несколько {основных|главных} {способов|методов}, {применяемых|используемых} {разными|различными} операционными системами. В числе {таких|таковых} {способов|методов} можно выделить четыре {метода|способа}:
· {критические|критичные} секции
· объекты исключительного владения
· {события|действия}
· синхронизация группой объектов
{Последовательно|Поочередно} {рассмотрим|разглядим} эти {основные|главные} {методы|способы}, используя в качестве примера функции по работе с глобальной кучей. Попробуем абстрактно разобраться со {свойствами|качествами} этих функций, что бы {понять|осознать}, какие {методы|способы} синхронизации и {в каких|в которых} {случаях|вариантах} {удобно|комфортно} {применять|использовать}.
Во–первых, глобальную кучу в целом можно {рассматривать|разглядывать} как {некий|некоторый} {сложный|непростой} объект, над которым могут {выполняться|производиться} {некоторые|некие} операции (пока мы рассматриваем {только|лишь} операции над кучей в целом, не вдаваясь в {нюансы|аспекты} работы с отдельными блоками — {при необходимости|по мере необходимости} доступ к отдельным блокам кучи должен быть синхронизирован, но это уже не функции кучи, а {проблема|неувязка} того, кто пользуется кучей).
Часть операций, {например|к примеру} получение указателя на какой–{либо|или} блок в куче, не нуждается в изменении самой кучи. {То есть|Другими словами} функции, осуществляющие подобные операции могут {выполняться|производиться} {одновременно|сразу} {разными|различными} потоками не конфликтуя друг с другом. Такие функции {удобно|комфортно} {назвать|именовать} “читателями” — они не изменяют кучу как единый объект.
{Другие|Остальные} операции, {например|к примеру} выделение {нового|новейшего} блока в куче, требуют внесения {изменений|конфигураций} в кучу — {изменения|конфигурации} в цепочке выделяемых блоков. Обычно такие {изменения|конфигурации} осуществляются не в одном месте, а требуется согласованное внесение {изменений|конфигураций} в нескольких структурах данных. В процессе {такой|таковой} операции структура кучи какое–то время оказывается нарушенной, вследствие {чего|чего же|что} одновременное выполнение {таких|таковых} действий {должно|обязано} быть исключено. Такие функции {удобно|комфортно} {назвать|именовать} “писателями” — они изменяют кучу как единый объект.
Применительно к куче {возможен|вероятен} одновременный доступ нескольких читателей и исключительный — писателей. {Более|Наиболее} того, если к куче получает доступ писатель, то читатели также должны быть лишены доступа (в {других|остальных} {случаях|вариантах} это {может быть|быть может} не так — читатели могут работать {одновременно|сразу} с писателем).
Можно {сформулировать|сконструировать} несколько правил для работы с {таким|таковым} объектом:
· если к объекту имеет доступ писатель, то ни читатели, ни {другие|остальные} писатели доступа не имеют;
· если к объекту имеет доступ читатель, то {возможен|вероятен} одновременный доступ {других|остальных} читателей и запрещен доступ писателям;
· если объект {свободен|волен}, то {первый|1-ый} пришедший писатель {или|либо} читатель имеет Право доступа.
Рассмотренный пример {очень|весьма} {удобен|комфортен}, {так как|потому что} {подобная|схожая} ситуация (много читателей, единственный писатель) встречается сплошь и — а {стандартного|обычного} объекта для синхронизации доступа к такому объекту нет. Благодаря этому {такой|таковой} пример становится благодатной почвой для рассмотрения {разных|различных} {способов|методов} синхронизации.
Номер
Поток, уже имеющий доступ
Поток, требующий доступа
действие
1
читатель
читатель
разрешить доступ
2
читатель
писатель
{ожидать|ждать} освобождения[1]
3
писатель
читатель
{ожидать|ждать} освобождения[1]
4
писатель
писатель
{ожидать|ждать} освобождения
5
—
читатель
разрешить доступ
6
—
писатель
разрешить доступ
Даже при {простейшем|простом} анализе {такой|таковой} таблицы можно {заметить|увидеть}, что писатели находятся в неравном положении — при {достаточно|довольно} {большом|большенном} числе читателей и писателей {возможна|вероятна} полная блокировка {последних|крайних}, {так как|потому что} читатели могут получать Право одновременного доступа к объекту, так что {возможна|вероятна} ситуация, когда объект {вообще|совершенно} не будет освобожден для писателей — хоть один читатель да найдется. Для выхода из {такой|таковой} ситуации следует слегка {модифицировать|видоизменять} реакцию объекта во 1м случае — если имеется ожидающий поток–писатель, то {надо|нужно} разрешить доступ ему, а не читателю. Для полной “симметрии” следует в 4м случае {проверять|инспектировать} наличие читателей и разрешать им доступ, даже если имеется ожидающий поток–писатель. {Такой|Таковой} механизм, хотя и {достаточно|довольно} {сложный|непростой} в реализации, обеспечит {более|наиболее}–{менее|наименее} равные права для выполнения потоков {разного|различного} типа.
Этот синхронизирующий объект может {использоваться|употребляться} {только|лишь} локально {внутри|снутри} процесса, создавшего его. {Остальные|Другие} объекты могут быть {использованы|применены} для синхронизации потоков {разных|различных} {процессов|действий}. {Название|Заглавие} объекта “{критическая|критичная} секция” {связано|соединено} с {некоторым|неким} абстрактным выделением части программного кода (секции), выполняющего {некоторые|некие} операции, порядок которых не {может быть|быть может} нарушен. {То есть|Другими словами} попытка {двумя|2-мя} {разными|различными} потоками {одновременно|сразу} {выполнять|делать} код {этой|данной|данной нам|данной для нас} секции приведет к ошибке.
{например|к примеру}, {такой|таковой} секцией {может быть|быть может} {удобно|комфортно} защитить функции–писатели, {так как|потому что} одновременный доступ нескольких писателей должен быть исключен.
Для {критической|критичной} секции вводят две операции:
· войти в секцию;
Пока какой–{либо|или} поток находится в {критической|критичной} секции, все {остальные|другие} потоки при попытке войти в нее будут {автоматически|автоматом} останавливаться в ожидании. Поток, уже вошедший в эту секцию, может {входить|заходить} в нее {многократно|неоднократно}, не {ожидая|ждя} ее освобождения.
· покинуть секцию;
При покидании потоком секции {уменьшается|миниатюризируется} счетчик числа вхождений этого потока в секцию, так что секция будет освобождена для {других|остальных} потоков {только|лишь} если поток выйдет из секции столько раз, сколько раз в нее {входил|заходил}. При освобождении {критической|критичной} секции будет пробужден {только|лишь} один поток, ожидающий разрешения на вход в эту секцию.
{Вообще|Совершенно} говоря, в {других|остальных} API, {отличных|хороших} от Win32 ({например|к примеру}, OS/2), {критическая|критичная} секция рассматривается не как синхронизирующий объект, {а как|как} фрагмент кода {программы|программки}, который может исполняться {только|лишь} одним потоком приложения. {То есть|Другими словами} вход в {критическую|критичную} секцию рассматривается как временное выключение механизма переключения потоков до выхода из {этой|данной|данной нам|данной для нас} секции. В Win32 API {критические|критичные} секции рассматриваются как объекты, что приводит к определенной {путанице|неурядице} — они {очень|весьма} близки по своим свойствам к неименованным объектам исключительного владения (mutex, см. ниже).
При использовании {критических|критичных} секций {надо|нужно} {следить|смотреть}, что бы в секции не выделялись {чересчур|очень} {большие|огромные} фрагменты кода, {так как|потому что} это может привести к {существенным|значимым} задержкам в выполнении {других|остальных} потоков.
{например|к примеру}, применительно к уже рассмотренным кучам — не имеет смысла все функции по работе с кучей защищать {критической|критичной} секцией, {так как|потому что} функции–читатели могут {выполняться|производиться} параллельно. {Более|Наиболее} того, применение {критической|критичной} секции даже для синхронизации писателей {на самом деле|по сути} представляется малоудобным — {так как|потому что} для синхронизации писателя с читателями {последним|крайним} все–равно придется {входить|заходить} в эту секцию, что {практически|фактически} приводит к защите всех функций единой секцией.
Можно выделить несколько случаев {эффективного|действенного} {применения|внедрения} {критических|критичных} секций:
· читатели не конфликтуют с писателями (защищать {надо|нужно} {только|лишь} писателей);
· все потоки имеют {примерно|приблизительно} равные права доступа (скажем, {нельзя|недозволено} выделить {чистых|незапятнанных} писателей и читателей);
· при построении составных синхронизирующих объектов, состоящих из нескольких {стандартных|обычных}, для защиты {последовательных|поочередных} операций над составным объектом.
Объекты исключительного владения — mutex (mut
ualex
clusion) — могут принадлежать {только|лишь} одному {потоку|сгустку} {одновременно|сразу}. Соответственно определяются операции над этими объектами:
· затребовать владение объектом;
При запросе владения система {проверяет|инспектирует}, {владеет|обладает}–ли какой–{либо|или} {другой|иной} поток {этим|сиим} объектом {или|либо} нет. Если имеется {другой|иной} поток–{владелец|обладатель}, то данный поток останавливается до {тех пор|того времени}, пока объект не освободиться. {Как только|Как} объект становится {свободным|вольным}, система {отдает|дает} его во владение {новому|новенькому} {потоку|сгустку}. Поток, уже {владеющий|обладающий} объектом, может {многократно|неоднократно} вступать во владение им.
· {освободить|высвободить} объект;
При освобождении объекта система просматривает, имеются–ли {другие|остальные} потоки, ожидающие освобождения этого объекта. Если имеются, то возобновит работу {только|лишь} один поток, а все {остальные|другие} продолжат ожидание — объект mutex {может быть|быть может} во владении {только|лишь} у {одного|1-го} потока. Освобождать объект может {только|лишь} тот поток, который им в данный момент {владеет|обладает}, {другие|остальные} потоки этого {сделать|создать} не могут. Для полного освобождения объекта поток должен столько раз {освободить|высвободить} его, сколько раз он затребовал владение с того момента, как ему дали этот объект во владение.
Если {учесть|учитывать}, что {владеть|обладать} объектом mutex может {только|лишь} один поток, то {получается|выходит}, что такие объекты похожи на {критические|критичные} секции — с того момента, как система {отдала|дала} объект во владение {потоку|сгустку} все {остальные|другие}, которые {захотят|захочут} получить его во владение, будут {ожидать|ждать} его освобождения. Отличия заключаются в {некоторых|неких} {нюансах|аспектах} использования — во–первых, объекты mutex могут быть {использованы|применены} {разными|различными} {процессами|действиями} (для этого предусмотрены именованные объекты, которые могут быть {использованы|применены} {другими|иными} {процессами|действиями}) и, во–вторых, {ожидать|ждать} владения {этим|сиим} объектом можно {разными|различными} {способами|методами} — с ограничением по времени {или|либо}, {например|к примеру}, {использовать|применять|употреблять} его для синхронизации {сразу|сходу} с несколькими объектами ({другими|иными} объектами mutex, семафорами, событиями и {прочим|иным}). {Об|О} этом — подробнее в {последующих|следующих} разделах.
{События|Действия}, как и объекты исключительного владения, могут {использоваться|употребляться} для синхронизации потоков, принадлежащих {разным|различным} приложениям. Самые {значительные|значимые} отличия сводятся к {следующему|последующему}:
· событиями никто не {владеет|обладает} — {то есть|другими словами} устанавливать {события|действия} в свободное {или|либо} занятое состояние могут любые потоки, имеющие право доступа к этому объекту
· {события|действия} различают {только|лишь} два состояния — свободное и занятое. сколько бы раз вы не переводили событие в занятое состояние, один единственный вызов функции, освобождающей это событие, {освободит|высвободит} его. И {наоборот|напротив}.
· в {классическом|традиционном} варианте освобождение {события|действия} разрешает {запуск|пуск} всех потоков, ожидающих его. Объекты исключительного владения и {критические|критичные} секции {позволяли|дозволяли} возобновить {исполнение|выполнение} {только|лишь} {одного|1-го} потока[2]
.
· смена состояния {события|действия} осуществляется в {любой|хоть какой} момент времени. Так, для вхождения в {критическую|критичную} секцию {или|либо} для получения объекта mutex во владение {необходимо|нужно} было дождаться их освобождения (что {выполнялось|производилось} {автоматически|автоматом}). Для событий это не так.
Соответственно, применительно к событиям, {говорят|молвят} о {двух|2-ух} {основных|главных} состояниях: {свободном|вольном} (установленном) и занятом (сброшенном) и о {трех|3-х} операциях, выполняемых над ними:
· сбросить событие;
Событие в сброшенном состоянии считается занятым. цвета). Опущенный флаг ({или|либо} выключенная лампа) означают, что такси занято. {Любой|Хоть какой} поток, имеющий доступ к событию, может сбросить его, независимо от того, какой поток это событие устанавливал.
· установить ({иногда|время от времени} — {послать|отправить}) событие;
Установленное (посланное) событие считается {свободным|вольным}. {Как только|Как} событие освобождается, все ожидающие его потоки могут возобновить свое {исполнение|выполнение} (см. сноску). Устанавливать событие может также {любой|хоть какой} поток.
· дождаться {события|действия};
{Так как|Потому что} сброс и установка событий происходит в {любой|хоть какой} момент времени, независимо от {предыдущего|предшествующего} состояния {события|действия}, то приходится вводить специальную операцию — дождаться освобождения объекта.
Эти {особенности|индивидуальности} выделяют {события|действия} в {особую|необыкновенную} категорию синхронизирующих объектов. Рассмотренные ранее {критические|критичные} секции и объекты исключительного владения {позволяют|разрешают} {осуществить|выполнить} монопольный доступ к какому–{либо|или} ресурсу {или|либо} объекту данных, в то время как {события|действия} определяют {некоторые|некие} условия, {после|опосля} которых {возможно|может быть} выполнение тех {или|либо} {иных|других} операций.
Пример. {Возвращаясь|Ворачиваясь} {к примеру|например} с глобальной кучей — для работы с ней {необходимо|нужно} {создать|сделать} составной синхронизирующий объект. Пример {такого|такового} объекта можно {найти|отыскать} в {книге|книжке} “Windows для {профессионалов|экспертов}” Джеффри Рихтера. естественно, логика построения объекта {одинакова|схожа} и в рассматриваемом случае, что {позволяет|дозволяет} детально {сравнить|сопоставить} несколько близких решений и заострить внимание на {некоторых|неких} “мелочах”. {Сейчас|На данный момент} мы {рассмотрим|разглядим} {только|лишь} “скелет” {такого|такового} объекта и {основные|главные} правила работы с ним. {Позже|Позднее}, {после|опосля} рассмотрения функций Win32 API, {рассмотрим|разглядим} {конкретную|определенную} реализацию этого составного объекта и сравним ее с {чрезвычайно|очень} {похожим|схожим} объектом, приведенным в {книге|книжке} Рихтера.
{Сначала|Поначалу} попробуем составить наличие хотя–бы {одного|1-го} читателя исключает для писателей возможность доступа к данным.
Из этих {соображений|суждений} следует наличие:
· {Критической|Критичной} секции {или|либо} объекта исключительного владения для синхронизации потоков–писателей. Выбор {одного|1-го} из этих объектов определяется необходимостью исключительного доступа {только|лишь} {одного|1-го} потока–писателя к данным. {Удобно|Комфортно} также, что {освободить|высвободить} секцию {или|либо} mutex может {только|лишь} тот поток, который его занял. В рассматриваемом примере будем {использовать|применять|употреблять} объект mutex, для большей схожести с Рихтером (это {позволит|дозволит} подчернуть несколько {нюансов|аспектов} в разработке {такого|такового} объекта).
· {События|Действия}, переходящего в занятое состояние при наличии хотя–бы {одного|1-го} читателя. В данном случае {целесообразно|целенаправлено} {выбрать|избрать} событие, которое будет сбрасываться в занятое состояние при {появлении|возникновении} первого потока–читателя и устанавливаться в свободное {последним|крайним} читателем ({последним|крайним} {из числа тех|из тех}, кто {пытается|пробует} {осуществить|выполнить} чтение {одновременно|сразу} с {другими|иными}, но не {вообще|совершенно} {последнего|крайнего}).
· Счетчика числа потоков–читателей, осуществляющих одновременный доступ. Нулевое состояние. При уменьшении счетчика проверяется {результат|итог} — если он 0, то событие устанавливается в свободное состояние.
Можно {примерно|приблизительно} {описать|обрисовать} структуру {такого|такового} объекта (назовем его NEWSWMRG, по {сравнению|сопоставлению} с объектом SWMRG, рассматриваемым у Рихтера — S
ingle W
riter M
ulti R
eader G
uard). Эта структура {должна|обязана} быть описана {примерно|приблизительно} так:
struct NEWSWMRG {
СОБЫТИЕ НЕТ_ЧИТАТЕЛЕЙ;
СЧЕТЧИК ЧИСЛО_ЧИТАТЕЛЕЙ;
объект_ИСКЛЮЧИТЕЛЬНОГО_ВЛАДЕНИЯ ЕСТЬ_ПИСАТЕЛИ;
};
Для работы с ней {надо|нужно} будет выделить четыре {специальных|особых} функции (инициализацию и удаление этого объекта пока не рассматриваем): две функции, {используемые|применяемые} потоками–читателями для получения доступа к данным и для обозначения конца операции чтения, {а также|также} две {аналогичных|подобных} функции для потоков–писателей.
void RequestWriter( NEWSWMRG* p ) {
// дождаться разрешения для писателя
Захватить объект ЕСТЬ_ПИСАТЕЛИ;
// если объект получен во владение — {других|остальных} писателей больше нет
// и пока мы его не освободим — не {появятся|покажутся}.
Дождаться {события|действия} НЕТ_ЧИТАТЕЛЕЙ;
// если событие установлено — читателей также нет
}
void ReleaseWriter( NEWSWMRG* p ) {
// {после|опосля} {изменения|конфигурации} данных разрешаем доступ {другим|иным|остальным} писателям и читателям
{Освободить|Высвободить} объект ЕСТЬ_ПИСАТЕЛИ;
}
void RequestReader( NEWSWMRG* p ) {
// дождаться разрешения для читателя — убедиться, что нет писателей
// для этого можно захватить объект ЕСТЬ_ПИСАТЕЛИ и {сразу|сходу} {освободить|высвободить} его
// захват пройдет {только|лишь} тогда, когда писателей нет.
Захватить объект ЕСТЬ_ПИСАТЕЛИ;
// реально {надо|нужно} {не только|не только лишь} убедиться в отсутствии писателей, {но и|да и}
// {увеличить|прирастить} счетчик и {при необходимости|по мере необходимости} сбросить событие НЕТ_ЧИТАТЕЛЕЙ
if ( ЧИСЛО_ЧИТАТЕЛЕЙ == 0 ) Сбросить событие НЕТ_ЧИТАТЕЛЕЙ в занятое;
ЧИСЛО_ЧИТАТЕЛЕЙ++;
// а вот {теперь|сейчас} можно смело освобождать объект ЕСТЬ_ПИСАТЕЛИ — во время
// работы читателя {достаточно|довольно} иметь сброшенное событие НЕТ_ЧИТАТЕЛЕЙ {Освободить|Высвободить} объект ЕСТЬ_ПИСАТЕЛИ;
}
void ReleaseReader( NEWSWMRG* p ) {
// {после|опосля} считывания данных уменьшаем счетчик и разрешаем доступ писателям
// при достижении нулевого значения счетчика.
—ЧИСЛО_ЧИТАТЕЛЕЙ;
if ( ЧИСЛО_ЧИТАТЕЛЕЙ == 0 ) Установить событие НЕТ_ЧИТАТЕЛЕЙ в свободное;
}
естественно, это еще не рабочая схема, а {только|лишь} намек на нее. {Полностью|Стопроцентно|На сто процентов|Вполне} обсудим {некоторые|некие} {особенности|индивидуальности} при рассмотрении функций Win32 API. На {первый|1-ый} {взгляд|взор} виден {небольшой|маленький|маленькой} “прокол” — в функции ReleaseReader счетчик {сначала|поначалу} {уменьшается|миниатюризируется}, а {только|лишь} {потом|позже} происходит проверка его значения и установка {события|действия} {при необходимости|по мере необходимости}. {Однако|Но} {возможен|вероятен} (хотя и {очень|весьма} маловероятен) {случай|вариант}, когда поток будет прерван для выполнения операций {другими|иными} потоками где–то {между|меж} уменьшением счетчика и установкой {события|действия}. В это время {другие|остальные} потоки могут {изменить|поменять} значение счетчика и событие будет установлено тогда, когда этого {делать|созодать} уже не следует.
Выйти из {этой|данной|данной нам|данной для нас} ситуации можно {разными|различными} {путями|способами} — {либо|или} добавлением еще {одного|1-го} объекта исключительного владения {или|либо} {критической|критичной} секции для упорядочивания операций со счетчиком, {либо|или} {другими|иными} {способами|методами}. Для разбирательства с этими {альтернативными|другими} {способами|методами} следует {рассмотреть|разглядеть} синхронизацию с группой объектов.
[1]
{Возможны|Вероятны} такие объекты, хотя это не {типичный|обычный} {случай|вариант}, когда читатели не конфликтуют с писателями. Тогда в ситуациях 2 и 3 следует разрешать доступ.
[2]
В Win32 API {существуют|есть} {специальные|особые} механизмы, {позволяющие|дозволяющие} возобновлять {исполнение|выполнение} {только|лишь} {одного|1-го} потока при освобожении {события|действия}. {Однако|Но}, по {сравнению|сопоставлению} с {другими|иными} операционными системами, скажем OS/2, такое синхронизация потоков
Для синхронизации действий, выполняемых различными потоками существует несколько разных методов. Условно их можно поделить на последующие:
· синхронизация при помощи глобальных переменных
· синхронизация при помощи обмена событиями
· синхронизация при помощи особых объектов (событий, семафоров, критичных секций, объектов исключительного владения и остальных)
1-ый способ синхронизации следует признать самым плохим, потому что он просит неизменного опроса состояния глобальной переменной. У этого способа есть и наиболее суровые недочеты — так, к примеру, вероятна полная блокировка потоков, если поток, ожидающий конфигурации глобальной переменной имеет наиболее высочайший ценность, чем поток, изменяющий эту переменную. правда, его можно несколько сделать лучше — вводя доп временные задержки меж поочередными опросами.
2-ой способ востребует сотворения объектов, способных получать сообщения либо уведомления о выполнении неких действий. Это могут быть окна, файлы (к примеру, при использовании асинхронных операций либо операций с извещением), сборники и т.д. В почти всех вариантах быть может комфортно сделать невидимое окно, участвующее в обмене сообщениями либо ожидающее получения сообщений для выполнения тех либо других действий.
3-ий способ — синхронизация при помощи особых объектов — востребует рассмотрения различных объектов и различных способов синхронизации с внедрением объектов. В Win32 API существует огромное число объектов, которые могут быть использованы в качестве синхронизирующих, при этом в почти всех вариантах заместо 1-го объекта может применяться объект другого типа. Потому будет любопытно разглядеть несколько главных способов синхронизации с внедрением объектов.
При рассмотрении методов синхронизации комфортно выделить несколько главных методов, используемых различными операционными системами. В числе таковых методов можно выделить четыре способа:
· критичные секции
· объекты исключительного владения
· действия
· синхронизация группой объектов
Поочередно разглядим эти главные способы, используя в качестве примера функции по работе с глобальной кучей. Попробуем абстрактно разобраться со качествами этих функций, что бы осознать, какие способы синхронизации и в которых вариантах комфортно использовать.
Во–первых, глобальную кучу в целом можно разглядывать как некоторый непростой объект, над которым могут производиться некие операции (пока мы рассматриваем лишь операции над кучей в целом, не вдаваясь в аспекты работы с отдельными блоками — по мере необходимости доступ к отдельным блокам кучи должен быть синхронизирован, но это уже не функции кучи, а неувязка того, кто пользуется кучей).
Часть операций, к примеру получение указателя на какой–или блок в куче, не нуждается в изменении самой кучи. Другими словами функции, осуществляющие подобные операции могут производиться сразу различными потоками не конфликтуя друг с другом. Такие функции комфортно именовать “читателями” — они не изменяют кучу как единый объект.
Остальные операции, к примеру выделение новейшего блока в куче, требуют внесения конфигураций в кучу — конфигурации в цепочке выделяемых блоков. Обычно такие конфигурации осуществляются не в одном месте, а требуется согласованное внесение конфигураций в нескольких структурах данных. В процессе таковой операции структура кучи какое–то время оказывается нарушенной, вследствие что одновременное выполнение таковых действий обязано быть исключено. Такие функции комфортно именовать “писателями” — они изменяют кучу как единый объект.
Применительно к куче вероятен одновременный доступ нескольких читателей и исключительный — писателей. Наиболее того, если к куче получает доступ писатель, то читатели также должны быть лишены доступа (в остальных вариантах это быть может не так — читатели могут работать сразу с писателем).
Можно сконструировать несколько правил для работы с таковым объектом:
· если к объекту имеет доступ писатель, то ни читатели, ни остальные писатели доступа не имеют;
· если к объекту имеет доступ читатель, то вероятен одновременный доступ остальных читателей и запрещен доступ писателям;
· если объект волен, то 1-ый пришедший писатель либо читатель имеет Право доступа.
Рассмотренный пример весьма комфортен, потому что схожая ситуация (много читателей, единственный писатель) встречается сплошь и — а обычного объекта для синхронизации доступа к такому объекту нет. Благодаря этому таковой пример становится благодатной почвой для рассмотрения различных методов синхронизации.
Номер
Поток, уже имеющий доступ
Поток, требующий доступа
действие
1
читатель
читатель
разрешить доступ
2
читатель
писатель
ждать освобождения[1]
3
писатель
читатель
ждать освобождения[1]
4
писатель
писатель
ждать освобождения
5
—
читатель
разрешить доступ
6
—
писатель
разрешить доступ
Даже при простом анализе таковой таблицы можно увидеть, что писатели находятся в неравном положении — при довольно большенном числе читателей и писателей вероятна полная блокировка крайних, потому что читатели могут получать Право одновременного доступа к объекту, так что вероятна ситуация, когда объект совершенно не будет освобожден для писателей — хоть один читатель да найдется. Для выхода из таковой ситуации следует слегка видоизменять реакцию объекта во 1м случае — если имеется ожидающий поток–писатель, то нужно разрешить доступ ему, а не читателю. Для полной “симметрии” следует в 4м случае инспектировать наличие читателей и разрешать им доступ, даже если имеется ожидающий поток–писатель. Таковой механизм, хотя и довольно непростой в реализации, обеспечит наиболее–наименее равные права для выполнения потоков различного типа.
Этот синхронизирующий объект может употребляться лишь локально снутри процесса, создавшего его. Другие объекты могут быть применены для синхронизации потоков различных действий. Заглавие объекта “критичная секция” соединено с неким абстрактным выделением части программного кода (секции), выполняющего некие операции, порядок которых не быть может нарушен. Другими словами попытка 2-мя различными потоками сразу делать код данной секции приведет к ошибке.
к примеру, таковой секцией быть может комфортно защитить функции–писатели, потому что одновременный доступ нескольких писателей должен быть исключен.
Для критичной секции вводят две операции:
· войти в секцию;
Пока какой–или поток находится в критичной секции, все другие потоки при попытке войти в нее будут автоматом останавливаться в ожидании. Поток, уже вошедший в эту секцию, может заходить в нее неоднократно, не ждя ее освобождения.
· покинуть секцию;
При покидании потоком секции миниатюризируется счетчик числа вхождений этого потока в секцию, так что секция будет освобождена для остальных потоков лишь если поток выйдет из секции столько раз, сколько раз в нее заходил. При освобождении критичной секции будет пробужден лишь один поток, ожидающий разрешения на вход в эту секцию.
Совершенно говоря, в остальных API, хороших от Win32 (к примеру, OS/2), критичная секция рассматривается не как синхронизирующий объект, как фрагмент кода программки, который может исполняться лишь одним потоком приложения. Другими словами вход в критичную секцию рассматривается как временное выключение механизма переключения потоков до выхода из данной секции. В Win32 API критичные секции рассматриваются как объекты, что приводит к определенной неурядице — они весьма близки по своим свойствам к неименованным объектам исключительного владения (mutex, см. ниже).
При использовании критичных секций нужно смотреть, что бы в секции не выделялись очень огромные фрагменты кода, потому что это может привести к значимым задержкам в выполнении остальных потоков.
к примеру, применительно к уже рассмотренным кучам — не имеет смысла все функции по работе с кучей защищать критичной секцией, потому что функции–читатели могут производиться параллельно. Наиболее того, применение критичной секции даже для синхронизации писателей по сути представляется малоудобным — потому что для синхронизации писателя с читателями крайним все–равно придется заходить в эту секцию, что фактически приводит к защите всех функций единой секцией.
Можно выделить несколько случаев действенного внедрения критичных секций:
· читатели не конфликтуют с писателями (защищать нужно лишь писателей);
· все потоки имеют приблизительно равные права доступа (скажем, недозволено выделить незапятнанных писателей и читателей);
· при построении составных синхронизирующих объектов, состоящих из нескольких обычных, для защиты поочередных операций над составным объектом.
Объекты исключительного владения — mutex (mut
ualex
clusion) — могут принадлежать лишь одному сгустку сразу. Соответственно определяются операции над этими объектами:
· затребовать владение объектом;
При запросе владения система инспектирует, обладает–ли какой–или иной поток сиим объектом либо нет. Если имеется иной поток–обладатель, то данный поток останавливается до того времени, пока объект не освободиться. Как объект становится вольным, система дает его во владение новенькому сгустку. Поток, уже обладающий объектом, может неоднократно вступать во владение им.
· высвободить объект;
При освобождении объекта система просматривает, имеются–ли остальные потоки, ожидающие освобождения этого объекта. Если имеются, то возобновит работу лишь один поток, а все другие продолжат ожидание — объект mutex быть может во владении лишь у 1-го потока. Освобождать объект может лишь тот поток, который им в данный момент обладает, остальные потоки этого создать не могут. Для полного освобождения объекта поток должен столько раз высвободить его, сколько раз он затребовал владение с того момента, как ему дали этот объект во владение.
Если учитывать, что обладать объектом mutex может лишь один поток, то выходит, что такие объекты похожи на критичные секции — с того момента, как система дала объект во владение сгустку все другие, которые захочут получить его во владение, будут ждать его освобождения. Отличия заключаются в неких аспектах использования — во–первых, объекты mutex могут быть применены различными действиями (для этого предусмотрены именованные объекты, которые могут быть применены иными действиями) и, во–вторых, ждать владения сиим объектом можно различными методами — с ограничением по времени либо, к примеру, применять его для синхронизации сходу с несколькими объектами (иными объектами mutex, семафорами, событиями и иным). О этом — подробнее в следующих разделах.
Действия, как и объекты исключительного владения, могут употребляться для синхронизации потоков, принадлежащих различным приложениям. Самые значимые отличия сводятся к последующему:
· событиями никто не обладает — другими словами устанавливать действия в свободное либо занятое состояние могут любые потоки, имеющие право доступа к этому объекту
· действия различают лишь два состояния — свободное и занятое. сколько бы раз вы не переводили событие в занятое состояние, один единственный вызов функции, освобождающей это событие, высвободит его. И напротив.
· в традиционном варианте освобождение действия разрешает пуск всех потоков, ожидающих его. Объекты исключительного владения и критичные секции дозволяли возобновить выполнение лишь 1-го потока[2]
.
· смена состояния действия осуществляется в хоть какой момент времени. Так, для вхождения в критичную секцию либо для получения объекта mutex во владение нужно было дождаться их освобождения (что производилось автоматом). Для событий это не так.
Соответственно, применительно к событиям, молвят о 2-ух главных состояниях: вольном (установленном) и занятом (сброшенном) и о 3-х операциях, выполняемых над ними:
· сбросить событие;
Событие в сброшенном состоянии считается занятым. цвета). Опущенный флаг (либо выключенная лампа) означают, что такси занято. Хоть какой поток, имеющий доступ к событию, может сбросить его, независимо от того, какой поток это событие устанавливал.
· установить (время от времени — отправить) событие;
Установленное (посланное) событие считается вольным. Как событие освобождается, все ожидающие его потоки могут возобновить свое выполнение (см. сноску). Устанавливать событие может также хоть какой поток.
· дождаться действия;
Потому что сброс и установка событий происходит в хоть какой момент времени, независимо от предшествующего состояния действия, то приходится вводить специальную операцию — дождаться освобождения объекта.
Эти индивидуальности выделяют действия в необыкновенную категорию синхронизирующих объектов. Рассмотренные ранее критичные секции и объекты исключительного владения разрешают выполнить монопольный доступ к какому–или ресурсу либо объекту данных, в то время как действия определяют некие условия, опосля которых может быть выполнение тех либо других операций.
Пример. Ворачиваясь например с глобальной кучей — для работы с ней нужно сделать составной синхронизирующий объект. Пример такового объекта можно отыскать в книжке “Windows для экспертов” Джеффри Рихтера. естественно, логика построения объекта схожа и в рассматриваемом случае, что дозволяет детально сопоставить несколько близких решений и заострить внимание на неких “мелочах”. На данный момент мы разглядим лишь “скелет” такового объекта и главные правила работы с ним. Позднее, опосля рассмотрения функций Win32 API, разглядим определенную реализацию этого составного объекта и сравним ее с очень схожим объектом, приведенным в книжке Рихтера.
Поначалу попробуем составить наличие хотя–бы 1-го читателя исключает для писателей возможность доступа к данным.
Из этих суждений следует наличие:
· Критичной секции либо объекта исключительного владения для синхронизации потоков–писателей. Выбор 1-го из этих объектов определяется необходимостью исключительного доступа лишь 1-го потока–писателя к данным. Комфортно также, что высвободить секцию либо mutex может лишь тот поток, который его занял. В рассматриваемом примере будем применять объект mutex, для большей схожести с Рихтером (это дозволит подчернуть несколько аспектов в разработке такового объекта).
· Действия, переходящего в занятое состояние при наличии хотя–бы 1-го читателя. В данном случае целенаправлено избрать событие, которое будет сбрасываться в занятое состояние при возникновении первого потока–читателя и устанавливаться в свободное крайним читателем (крайним из тех, кто пробует выполнить чтение сразу с иными, но не совершенно крайнего).
· Счетчика числа потоков–читателей, осуществляющих одновременный доступ. Нулевое состояние. При уменьшении счетчика проверяется итог — если он 0, то событие устанавливается в свободное состояние.
Можно приблизительно обрисовать структуру такового объекта (назовем его NEWSWMRG, по сопоставлению с объектом SWMRG, рассматриваемым у Рихтера — S
ingle W
riter M
ulti R
eader G
uard). Эта структура обязана быть описана приблизительно так:
struct NEWSWMRG {
СОБЫТИЕ НЕТ_ЧИТАТЕЛЕЙ;
СЧЕТЧИК ЧИСЛО_ЧИТАТЕЛЕЙ;
объект_ИСКЛЮЧИТЕЛЬНОГО_ВЛАДЕНИЯ ЕСТЬ_ПИСАТЕЛИ;
};
Для работы с ней нужно будет выделить четыре особых функции (инициализацию и удаление этого объекта пока не рассматриваем): две функции, применяемые потоками–читателями для получения доступа к данным и для обозначения конца операции чтения, также две подобных функции для потоков–писателей.
void RequestWriter( NEWSWMRG* p ) {
// дождаться разрешения для писателя
Захватить объект ЕСТЬ_ПИСАТЕЛИ;
// если объект получен во владение — остальных писателей больше нет
// и пока мы его не освободим — не покажутся.
Дождаться действия НЕТ_ЧИТАТЕЛЕЙ;
// если событие установлено — читателей также нет
}
void ReleaseWriter( NEWSWMRG* p ) {
// опосля конфигурации данных разрешаем доступ иным писателям и читателям
Высвободить объект ЕСТЬ_ПИСАТЕЛИ;
}
void RequestReader( NEWSWMRG* p ) {
// дождаться разрешения для читателя — убедиться, что нет писателей
// для этого можно захватить объект ЕСТЬ_ПИСАТЕЛИ и сходу высвободить его
// захват пройдет лишь тогда, когда писателей нет.
Захватить объект ЕСТЬ_ПИСАТЕЛИ;
// реально нужно не только лишь убедиться в отсутствии писателей, да и
// прирастить счетчик и по мере необходимости сбросить событие НЕТ_ЧИТАТЕЛЕЙ
if ( ЧИСЛО_ЧИТАТЕЛЕЙ == 0 ) Сбросить событие НЕТ_ЧИТАТЕЛЕЙ в занятое;
ЧИСЛО_ЧИТАТЕЛЕЙ++;
// а вот сейчас можно смело освобождать объект ЕСТЬ_ПИСАТЕЛИ — во время
// работы читателя довольно иметь сброшенное событие НЕТ_ЧИТАТЕЛЕЙ Высвободить объект ЕСТЬ_ПИСАТЕЛИ;
}
void ReleaseReader( NEWSWMRG* p ) {
// опосля считывания данных уменьшаем счетчик и разрешаем доступ писателям
// при достижении нулевого значения счетчика.
—ЧИСЛО_ЧИТАТЕЛЕЙ;
if ( ЧИСЛО_ЧИТАТЕЛЕЙ == 0 ) Установить событие НЕТ_ЧИТАТЕЛЕЙ в свободное;
}
естественно, это еще не рабочая схема, а лишь намек на нее. На сто процентов обсудим некие индивидуальности при рассмотрении функций Win32 API. На 1-ый взор виден маленький “прокол” — в функции ReleaseReader счетчик поначалу миниатюризируется, а лишь позже происходит проверка его значения и установка действия по мере необходимости. Но вероятен (хотя и весьма маловероятен) вариант, когда поток будет прерван для выполнения операций иными потоками где–то меж уменьшением счетчика и установкой действия. В это время остальные потоки могут поменять значение счетчика и событие будет установлено тогда, когда этого созодать уже не следует.
Выйти из данной ситуации можно различными способами — или добавлением еще 1-го объекта исключительного владения либо критичной секции для упорядочивания операций со счетчиком, или иными методами. Для разбирательства с этими другими методами следует разглядеть синхронизацию с группой объектов.
[1]
Вероятны такие объекты, хотя это не обычный вариант, когда читатели не конфликтуют с писателями. Тогда в ситуациях 2 и 3 следует разрешать доступ.
[2]
В Win32 API есть особые механизмы, дозволяющие возобновлять выполнение лишь 1-го потока при освобожении действия. Но, по сопоставлению с иными операционными системами, скажем OS/2, такое синхронизация потоков
Для синхронизации действий, выполняемых различными потоками существует несколько разных методов. Условно их можно поделить на последующие:
· синхронизация при помощи глобальных переменных
· синхронизация при помощи обмена событиями
· синхронизация при помощи особых объектов (событий, семафоров, критичных секций, объектов исключительного владения и остальных)
1-ый способ синхронизации следует признать самым плохим, потому что он просит неизменного опроса состояния глобальной переменной. У этого способа есть и наиболее суровые недочеты — так, к примеру, вероятна полная блокировка потоков, если поток, ожидающий конфигурации глобальной переменной имеет наиболее высочайший ценность, чем поток, изменяющий эту переменную. правда, его можно несколько сделать лучше — вводя доп временные задержки меж поочередными опросами.
2-ой способ востребует сотворения объектов, способных получать сообщения либо уведомления о выполнении неких действий. Это могут быть окна, файлы (к примеру, при использовании асинхронных операций либо операций с извещением), сборники и т.д. В почти всех вариантах быть может комфортно сделать невидимое окно, участвующее в обмене сообщениями либо ожидающее получения сообщений для выполнения тех либо других действий.
3-ий способ — синхронизация при помощи особых объектов — востребует рассмотрения различных объектов и различных способов синхронизации с внедрением объектов. В Win32 API существует огромное число объектов, которые могут быть использованы в качестве синхронизирующих, при этом в почти всех вариантах заместо 1-го объекта может применяться объект другого типа. Потому будет любопытно разглядеть несколько главных способов синхронизации с внедрением объектов.
При рассмотрении методов синхронизации комфортно выделить несколько главных методов, используемых различными операционными системами. В числе таковых методов можно выделить четыре способа:
· критичные секции
· объекты исключительного владения
· действия
· синхронизация группой объектов
Поочередно разглядим эти главные способы, используя в качестве примера функции по работе с глобальной кучей. Попробуем абстрактно разобраться со качествами этих функций, что бы осознать, какие способы синхронизации и в которых вариантах комфортно использовать.
Во–первых, глобальную кучу в целом можно разглядывать как некоторый непростой объект, над которым могут производиться некие операции (пока мы рассматриваем лишь операции над кучей в целом, не вдаваясь в аспекты работы с отдельными блоками — по мере необходимости доступ к отдельным блокам кучи должен быть синхронизирован, но это уже не функции кучи, а неувязка того, кто пользуется кучей).
Часть операций, к примеру получение указателя на какой–или блок в куче, не нуждается в изменении самой кучи. Другими словами функции, осуществляющие подобные операции могут производиться сразу различными потоками не конфликтуя друг с другом. Такие функции комфортно именовать “читателями” — они не изменяют кучу как единый объект.
Остальные операции, к примеру выделение новейшего блока в куче, требуют внесения конфигураций в кучу — конфигурации в цепочке выделяемых блоков. Обычно такие конфигурации осуществляются не в одном месте, а требуется согласованное внесение конфигураций в нескольких структурах данных. В процессе таковой операции структура кучи какое–то время оказывается нарушенной, вследствие что одновременное выполнение таковых действий обязано быть исключено. Такие функции комфортно именовать “писателями” — они изменяют кучу как единый объект.
Применительно к куче вероятен одновременный доступ нескольких читателей и исключительный — писателей. Наиболее того, если к куче получает доступ писатель, то читатели также должны быть лишены доступа (в остальных вариантах это быть может не так — читатели могут работать сразу с писателем).
Можно сконструировать несколько правил для работы с таковым объектом:
· если к объекту имеет доступ писатель, то ни читатели, ни остальные писатели доступа не имеют;
· если к объекту имеет доступ читатель, то вероятен одновременный доступ остальных читателей и запрещен доступ писателям;
· если объект волен, то 1-ый пришедший писатель либо читатель имеет Право доступа.
Рассмотренный пример весьма комфортен, потому что схожая ситуация (много читателей, единственный писатель) встречается сплошь и — а обычного объекта для синхронизации доступа к такому объекту нет. Благодаря этому таковой пример становится благодатной почвой для рассмотрения различных методов синхронизации.
Номер
Поток, уже имеющий доступ
Поток, требующий доступа
действие
1
читатель
читатель
разрешить доступ
2
читатель
писатель
ждать освобождения[1]
3
писатель
читатель
ждать освобождения[1]
4
писатель
писатель
ждать освобождения
5
—
читатель
разрешить доступ
6
—
писатель
разрешить доступ
Даже при простом анализе таковой таблицы можно увидеть, что писатели находятся в неравном положении — при довольно большенном числе читателей и писателей вероятна полная блокировка крайних, потому что читатели могут получать Право одновременного доступа к объекту, так что вероятна ситуация, когда объект совершенно не будет освобожден для писателей — хоть один читатель да найдется. Для выхода из таковой ситуации следует слегка видоизменять реакцию объекта во 1м случае — если имеется ожидающий поток–писатель, то нужно разрешить доступ ему, а не читателю. Для полной “симметрии” следует в 4м случае инспектировать наличие читателей и разрешать им доступ, даже если имеется ожидающий поток–писатель. Таковой механизм, хотя и довольно непростой в реализации, обеспечит наиболее–наименее равные права для выполнения потоков различного типа.
Этот синхронизирующий объект может употребляться лишь локально снутри процесса, создавшего его. Другие объекты могут быть применены для синхронизации потоков различных действий. Заглавие объекта “критичная секция” соединено с неким абстрактным выделением части программного кода (секции), выполняющего некие операции, порядок которых не быть может нарушен. Другими словами попытка 2-мя различными потоками сразу делать код данной секции приведет к ошибке.
к примеру, таковой секцией быть может комфортно защитить функции–писатели, потому что одновременный доступ нескольких писателей должен быть исключен.
Для критичной секции вводят две операции:
· войти в секцию;
Пока какой–или поток находится в критичной секции, все другие потоки при попытке войти в нее будут автоматом останавливаться в ожидании. Поток, уже вошедший в эту секцию, может заходить в нее неоднократно, не ждя ее освобождения.
· покинуть секцию;
При покидании потоком секции миниатюризируется счетчик числа вхождений этого потока в секцию, так что секция будет освобождена для остальных потоков лишь если поток выйдет из секции столько раз, сколько раз в нее заходил. При освобождении критичной секции будет пробужден лишь один поток, ожидающий разрешения на вход в эту секцию.
Совершенно говоря, в остальных API, хороших от Win32 (к примеру, OS/2), критичная секция рассматривается не как синхронизирующий объект, как фрагмент кода программки, который может исполняться лишь одним потоком приложения. Другими словами вход в критичную секцию рассматривается как временное выключение механизма переключения потоков до выхода из данной секции. В Win32 API критичные секции рассматриваются как объекты, что приводит к определенной неурядице — они весьма близки по своим свойствам к неименованным объектам исключительного владения (mutex, см. ниже).
При использовании критичных секций нужно смотреть, что бы в секции не выделялись очень огромные фрагменты кода, потому что это может привести к значимым задержкам в выполнении остальных потоков.
к примеру, применительно к уже рассмотренным кучам — не имеет смысла все функции по работе с кучей защищать критичной секцией, потому что функции–читатели могут производиться параллельно. Наиболее того, применение критичной секции даже для синхронизации писателей по сути представляется малоудобным — потому что для синхронизации писателя с читателями крайним все–равно придется заходить в эту секцию, что фактически приводит к защите всех функций единой секцией.
Можно выделить несколько случаев действенного внедрения критичных секций:
· читатели не конфликтуют с писателями (защищать нужно лишь писателей);
· все потоки имеют приблизительно равные права доступа (скажем, недозволено выделить незапятнанных писателей и читателей);
· при построении составных синхронизирующих объектов, состоящих из нескольких обычных, для защиты поочередных операций над составным объектом.
Объекты исключительного владения — mutex (mut
ualex
clusion) — могут принадлежать лишь одному сгустку сразу. Соответственно определяются операции над этими объектами:
· затребовать владение объектом;
При запросе владения система инспектирует, обладает–ли какой–или иной поток сиим объектом либо нет. Если имеется иной поток–обладатель, то данный поток останавливается до того времени, пока объект не освободиться. Как объект становится вольным, система дает его во владение новенькому сгустку. Поток, уже обладающий объектом, может неоднократно вступать во владение им.
· высвободить объект;
При освобождении объекта система просматривает, имеются–ли остальные потоки, ожидающие освобождения этого объекта. Если имеются, то возобновит работу лишь один поток, а все другие продолжат ожидание — объект mutex быть может во владении лишь у 1-го потока. Освобождать объект может лишь тот поток, который им в данный момент обладает, остальные потоки этого создать не могут. Для полного освобождения объекта поток должен столько раз высвободить его, сколько раз он затребовал владение с того момента, как ему дали этот объект во владение.
Если учитывать, что обладать объектом mutex может лишь один поток, то выходит, что такие объекты похожи на критичные секции — с того момента, как система дала объект во владение сгустку все другие, которые захочут получить его во владение, будут ждать его освобождения. Отличия заключаются в неких аспектах использования — во–первых, объекты mutex могут быть применены различными действиями (для этого предусмотрены именованные объекты, которые могут быть применены иными действиями) и, во–вторых, ждать владения сиим объектом можно различными методами — с ограничением по времени либо, к примеру, применять его для синхронизации сходу с несколькими объектами (иными объектами mutex, семафорами, событиями и иным). О этом — подробнее в следующих разделах.
Действия, как и объекты исключительного владения, могут употребляться для синхронизации потоков, принадлежащих различным приложениям. Самые значимые отличия сводятся к последующему:
· событиями никто не обладает — другими словами устанавливать действия в свободное либо занятое состояние могут любые потоки, имеющие право доступа к этому объекту
· действия различают лишь два состояния — свободное и занятое. сколько бы раз вы не переводили событие в занятое состояние, один единственный вызов функции, освобождающей это событие, высвободит его. И напротив.
· в традиционном варианте освобождение действия разрешает пуск всех потоков, ожидающих его. Объекты исключительного владения и критичные секции дозволяли возобновить выполнение лишь 1-го потока[2]
.
· смена состояния действия осуществляется в хоть какой момент времени. Так, для вхождения в критичную секцию либо для получения объекта mutex во владение нужно было дождаться их освобождения (что производилось автоматом). Для событий это не так.
Соответственно, применительно к событиям, молвят о 2-ух главных состояниях: вольном (установленном) и занятом (сброшенном) и о 3-х операциях, выполняемых над ними:
· сбросить событие;
Событие в сброшенном состоянии считается занятым. действий) в каких-то свойствах Умозаключение по аналогии — познание приобретенное из рассмотрения какого-нибудь объекта переносится на наименее изученный сходны — флаг такси (в Рф — лампа зеленоватого цвета). Опущенный флаг (либо выключенная лампа) означают, что такси занято. Хоть какой поток, имеющий доступ к событию, может сбросить его, независимо от того, какой поток это событие устанавливал.
· установить (время от времени — отправить) событие;
Установленное (посланное) событие считается вольным. Как событие освобождается, все ожидающие его потоки могут возобновить свое выполнение (см. сноску). Устанавливать событие может также хоть какой поток.
· дождаться действия;
Потому что сброс и установка событий происходит в хоть какой момент времени, независимо от предшествующего состояния действия, то приходится вводить специальную операцию — дождаться освобождения объекта.
Эти индивидуальности выделяют действия в необыкновенную категорию синхронизирующих объектов. Рассмотренные ранее критичные секции и объекты исключительного владения разрешают выполнить монопольный доступ к какому–или ресурсу либо объекту данных, в то время как действия определяют некие условия, опосля которых может быть выполнение тех либо других операций.
Пример. Ворачиваясь например с глобальной кучей — для работы с ней нужно сделать составной синхронизирующий объект. Пример такового объекта можно отыскать в книжке “Windows для экспертов” Джеффри Рихтера. естественно, логика построения объекта схожа и в рассматриваемом случае, что дозволяет детально сопоставить несколько близких решений и заострить внимание на неких “мелочах”. На данный момент мы разглядим лишь “скелет” такового объекта и главные правила работы с ним. Позднее, опосля рассмотрения функций Win32 API, разглядим определенную реализацию этого составного объекта и сравним ее с очень схожим объектом, приведенным в книжке Рихтера.
Поначалу попробуем составить обычно наименее ярки и наименее детальны чем образы восприятия но в их находит отражение самое свойственное для данного предмета Различия в яркости стойкости и точности представлений памяти весьма инди о тех обычных объектах, которые нужно применять для построения составного синхронизирующего объекта. Мы имеем дело с потоками–писателями, имеющими исключительный доступ к данным, и потоками–читателями, которые могут иметь одновременный доступ к тем–же данным. Но наличие хотя–бы 1-го читателя исключает для писателей возможность доступа к данным.
Из этих суждений следует наличие:
· Критичной секции либо объекта исключительного владения для синхронизации потоков–писателей. Выбор 1-го из этих объектов определяется необходимостью исключительного доступа лишь 1-го потока–писателя к данным. Комфортно также, что высвободить секцию либо mutex может лишь тот поток, который его занял. В рассматриваемом примере будем применять объект mutex, для большей схожести с Рихтером (это дозволит подчернуть несколько аспектов в разработке такового объекта).
· Действия, переходящего в занятое состояние при наличии хотя–бы 1-го читателя. В данном случае целенаправлено избрать событие, которое будет сбрасываться в занятое состояние при возникновении первого потока–читателя и устанавливаться в свободное крайним читателем (крайним из тех, кто пробует выполнить чтение сразу с иными, но не совершенно крайнего).
· Счетчика числа потоков–читателей, осуществляющих одновременный доступ. Нулевое индивидумом общественно-исторического опыта Запечатлено в схемах действий понятиях соц ролях нормах и ценностях Система значений индивидума обусловливает управление действиями его деятельности» счетчика соответствует установленному в свободное состояние событию. При увеличении счетчика проверяется его изначальное индивидумом общественно-исторического опыта Запечатлено в схемах действий понятиях соц ролях нормах и ценностях Система значений индивидума обусловливает управление действиями его деятельности», и если оно было 0, то событие сбрасывается в занятое состояние. При уменьшении счетчика проверяется итог — если он 0, то событие устанавливается в свободное состояние.
Можно приблизительно обрисовать структуру такового объекта (назовем его NEWSWMRG, по сопоставлению с объектом SWMRG, рассматриваемым у Рихтера — S
ingle W
riter M
ulti R
eader G
uard). Эта структура обязана быть описана приблизительно так:
struct NEWSWMRG
СОБЫТИЕ НЕТ_ЧИТАТЕЛЕЙ;
СЧЕТЧИК ЧИСЛО_ЧИТАТЕЛЕЙ;
объект_ИСКЛЮЧИТЕЛЬНОГО_ВЛАДЕНИЯ ЕСТЬ_ПИСАТЕЛИ;
;
Для работы с ней нужно будет выделить четыре особых функции (инициализацию и удаление этого объекта пока не рассматриваем): две функции, применяемые потоками–читателями для получения доступа к данным и для обозначения конца операции чтения, также две подобных функции для потоков–писателей.
void RequestWriter( NEWSWMRG* p )
void ReleaseWriter( NEWSWMRG* p )
// опосля конфигурации данных разрешаем доступ иным писателям и читателям
Высвободить объект ЕСТЬ_ПИСАТЕЛИ;
void RequestReader( NEWSWMRG* p )
void ReleaseReader( NEWSWMRG* p )
// опосля считывания данных уменьшаем счетчик и разрешаем доступ писателям
// при достижении нулевого значения счетчика.
—ЧИСЛО_ЧИТАТЕЛЕЙ;
if ( ЧИСЛО_ЧИТАТЕЛЕЙ == 0 ) Установить событие НЕТ_ЧИТАТЕЛЕЙ в свободное;
естественно, это еще не рабочая схема, а лишь намек на нее. На сто процентов обсудим некие индивидуальности при рассмотрении функций Win32 API. На 1-ый взор виден маленький “прокол” — в функции ReleaseReader счетчик поначалу миниатюризируется, а лишь позже происходит проверка его значения и установка действия по мере необходимости. Но вероятен (хотя и весьма маловероятен) вариант, когда поток будет прерван для выполнения операций иными потоками где–то меж уменьшением счетчика и установкой действия. В это время остальные потоки могут поменять значение счетчика и событие будет установлено тогда, когда этого созодать уже не следует.
Выйти из данной ситуации можно различными способами — или добавлением еще 1-го объекта исключительного владения либо критичной секции для упорядочивания операций со счетчиком, или иными методами. Для разбирательства с этими другими методами следует разглядеть синхронизацию с группой объектов.
[1]
Вероятны такие объекты, хотя это не обычный вариант, когда читатели не конфликтуют с писателями. Тогда в ситуациях 2 и 3 следует разрешать доступ.
[2]
В Win32 API есть особые механизмы, дозволяющие возобновлять выполнение лишь 1-го потока при освобожении действия. Но, по сопоставлению с иными операционными системами, скажем OS/2, такое звериного организма служащая для воплощения контакта с миром вокруг нас В базе поведения лежат потребности звериного организма над которыми надстраиваются исполнительные деяния служащие действия необычно.
]]>
Для синхронизации действий, выполняемых разными потоками существует несколько различных способов. Условно их можно разделить на следующие:
· синхронизация с помощью глобальных переменных
· синхронизация с помощью обмена событиями
· синхронизация с помощью специальных объектов (событий, семафоров, критических секций, объектов исключительного владения и других)
Первый метод синхронизации следует признать самым неудачным, так как он требует постоянного опроса состояния глобальной переменной. У этого метода есть и более серьезные недостатки — так, например, возможна полная блокировка потоков, если поток, ожидающий изменения глобальной переменной имеет более высокий приоритет, чем поток, изменяющий эту переменную. правда, его можно несколько улучшить — вводя дополнительные временные задержки между последовательными опросами.
Второй метод потребует создания объектов, способных получать сообщения или извещения о выполнении некоторых действий. Это могут быть окна, файлы (например, при использовании асинхронных операций или операций с уведомлением), каталоги и т.д. Во многих случаях может быть удобно создать невидимое окно, участвующее в обмене сообщениями или ожидающее получения сообщений для выполнения тех или иных действий.
Третий метод — синхронизация с помощью специальных объектов — потребует рассмотрения разных объектов и разных методов синхронизации с использованием объектов. В Win32 API существует большое число объектов, которые могут быть применены в качестве синхронизирующих, причем во многих случаях вместо одного объекта может применяться объект другого типа. Поэтому будет интересно рассмотреть несколько основных методов синхронизации с использованием объектов.
При рассмотрении способов синхронизации удобно выделить несколько основных способов, применяемых разными операционными системами. В числе таких способов можно выделить четыре метода:
· критические секции
· объекты исключительного владения
· события
· синхронизация группой объектов
Последовательно рассмотрим эти основные методы, используя в качестве примера функции по работе с глобальной кучей. Попробуем абстрактно разобраться со свойствами этих функций, что бы понять, какие методы синхронизации и в каких случаях удобно применять.
Во–первых, глобальную кучу в целом можно рассматривать как некий сложный объект, над которым могут выполняться некоторые операции (пока мы рассматриваем только операции над кучей в целом, не вдаваясь в нюансы работы с отдельными блоками — при необходимости доступ к отдельным блокам кучи должен быть синхронизирован, но это уже не функции кучи, а проблема того, кто пользуется кучей).
Часть операций, например получение указателя на какой–либо блок в куче, не нуждается в изменении самой кучи. То есть функции, осуществляющие подобные операции могут выполняться одновременно разными потоками не конфликтуя друг с другом. Такие функции удобно назвать “читателями” — они не изменяют кучу как единый объект.
Другие операции, например выделение нового блока в куче, требуют внесения изменений в кучу — изменения в цепочке выделяемых блоков. Обычно такие изменения осуществляются не в одном месте, а требуется согласованное внесение изменений в нескольких структурах данных. В процессе такой операции структура кучи какое–то время оказывается нарушенной, вследствие чего одновременное выполнение таких действий должно быть исключено. Такие функции удобно назвать “писателями” — они изменяют кучу как единый объект.
Применительно к куче возможен одновременный доступ нескольких читателей и исключительный — писателей. Более того, если к куче получает доступ писатель, то читатели также должны быть лишены доступа (в других случаях это может быть не так — читатели могут работать одновременно с писателем).
Можно сформулировать несколько правил для работы с таким объектом:
· если к объекту имеет доступ писатель, то ни читатели, ни другие писатели доступа не имеют;
· если к объекту имеет доступ читатель, то возможен одновременный доступ других читателей и запрещен доступ писателям;
· если объект свободен, то первый пришедший писатель или читатель имеет Право доступа.
Рассмотренный пример очень удобен, так как подобная ситуация (много читателей, единственный писатель) встречается сплошь и — а стандартного объекта для синхронизации доступа к такому объекту нет. Благодаря этому такой пример становится благодатной почвой для рассмотрения разных способов синхронизации.
Номер
Поток, уже имеющий доступ
Поток, требующий доступа
действие
1
читатель
читатель
разрешить доступ
2
читатель
писатель
ожидать освобождения[1]
3
писатель
читатель
ожидать освобождения[1]
4
писатель
писатель
ожидать освобождения
5
—
читатель
разрешить доступ
6
—
писатель
разрешить доступ
Даже при простейшем анализе такой таблицы можно заметить, что писатели находятся в неравном положении — при достаточно большом числе читателей и писателей возможна полная блокировка последних, так как читатели могут получать Право одновременного доступа к объекту, так что возможна ситуация, когда объект вообще не будет освобожден для писателей — хоть один читатель да найдется. Для выхода из такой ситуации следует слегка модифицировать реакцию объекта во 1м случае — если имеется ожидающий поток–писатель, то надо разрешить доступ ему, а не читателю. Для полной “симметрии” следует в 4м случае проверять наличие читателей и разрешать им доступ, даже если имеется ожидающий поток–писатель. Такой механизм, хотя и достаточно сложный в реализации, обеспечит более–менее равные права для выполнения потоков разного типа.
Этот синхронизирующий объект может использоваться только локально внутри процесса, создавшего его. Остальные объекты могут быть использованы для синхронизации потоков разных процессов. Название объекта “критическая секция” связано с некоторым абстрактным выделением части программного кода (секции), выполняющего некоторые операции, порядок которых не может быть нарушен. То есть попытка двумя разными потоками одновременно выполнять код этой секции приведет к ошибке.
например, такой секцией может быть удобно защитить функции–писатели, так как одновременный доступ нескольких писателей должен быть исключен.
Для критической секции вводят две операции:
· войти в секцию;
Пока какой–либо поток находится в критической секции, все остальные потоки при попытке войти в нее будут автоматически останавливаться в ожидании. Поток, уже вошедший в эту секцию, может входить в нее многократно, не ожидая ее освобождения.
· покинуть секцию;
При покидании потоком секции уменьшается счетчик числа вхождений этого потока в секцию, так что секция будет освобождена для других потоков только если поток выйдет из секции столько раз, сколько раз в нее входил. При освобождении критической секции будет пробужден только один поток, ожидающий разрешения на вход в эту секцию.
Вообще говоря, в других API, отличных от Win32 (например, OS/2), критическая секция рассматривается не как синхронизирующий объект, а как фрагмент кода программы, который может исполняться только одним потоком приложения. То есть вход в критическую секцию рассматривается как временное выключение механизма переключения потоков до выхода из этой секции. В Win32 API критические секции рассматриваются как объекты, что приводит к определенной путанице — они очень близки по своим свойствам к неименованным объектам исключительного владения (mutex, см. ниже).
При использовании критических секций надо следить, что бы в секции не выделялись чересчур большие фрагменты кода, так как это может привести к существенным задержкам в выполнении других потоков.
например, применительно к уже рассмотренным кучам — не имеет смысла все функции по работе с кучей защищать критической секцией, так как функции–читатели могут выполняться параллельно. Более того, применение критической секции даже для синхронизации писателей на самом деле представляется малоудобным — так как для синхронизации писателя с читателями последним все–равно придется входить в эту секцию, что практически приводит к защите всех функций единой секцией.
Можно выделить несколько случаев эффективного применения критических секций:
· читатели не конфликтуют с писателями (защищать надо только писателей);
· все потоки имеют примерно равные права доступа (скажем, нельзя выделить чистых писателей и читателей);
· при построении составных синхронизирующих объектов, состоящих из нескольких стандартных, для защиты последовательных операций над составным объектом.
Объекты исключительного владения — mutex (mut
ualex
clusion) — могут принадлежать только одному потоку одновременно. Соответственно определяются операции над этими объектами:
· затребовать владение объектом;
При запросе владения система проверяет, владеет–ли какой–либо другой поток этим объектом или нет. Если имеется другой поток–владелец, то данный поток останавливается до тех пор, пока объект не освободиться. Как только объект становится свободным, система отдает его во владение новому потоку. Поток, уже владеющий объектом, может многократно вступать во владение им.
· освободить объект;
При освобождении объекта система просматривает, имеются–ли другие потоки, ожидающие освобождения этого объекта. Если имеются, то возобновит работу только один поток, а все остальные продолжат ожидание — объект mutex может быть во владении только у одного потока. Освобождать объект может только тот поток, который им в данный момент владеет, другие потоки этого сделать не могут. Для полного освобождения объекта поток должен столько раз освободить его, сколько раз он затребовал владение с того момента, как ему дали этот объект во владение.
Если учесть, что владеть объектом mutex может только один поток, то получается, что такие объекты похожи на критические секции — с того момента, как система отдала объект во владение потоку все остальные, которые захотят получить его во владение, будут ожидать его освобождения. Отличия заключаются в некоторых нюансах использования — во–первых, объекты mutex могут быть использованы разными процессами (для этого предусмотрены именованные объекты, которые могут быть использованы другими процессами) и, во–вторых, ожидать владения этим объектом можно разными способами — с ограничением по времени или, например, использовать его для синхронизации сразу с несколькими объектами (другими объектами mutex, семафорами, событиями и прочим). Об этом — подробнее в последующих разделах.
События, как и объекты исключительного владения, могут использоваться для синхронизации потоков, принадлежащих разным приложениям. Самые значительные отличия сводятся к следующему:
· событиями никто не владеет — то есть устанавливать события в свободное или занятое состояние могут любые потоки, имеющие право доступа к этому объекту
· события различают только два состояния — свободное и занятое. сколько бы раз вы не переводили событие в занятое состояние, один единственный вызов функции, освобождающей это событие, освободит его. И наоборот.
· в классическом варианте освобождение события разрешает запуск всех потоков, ожидающих его. Объекты исключительного владения и критические секции позволяли возобновить исполнение только одного потока[2]
.
· смена состояния события осуществляется в любой момент времени. Так, для вхождения в критическую секцию или для получения объекта mutex во владение необходимо было дождаться их освобождения (что выполнялось автоматически). Для событий это не так.
Соответственно, применительно к событиям, говорят о двух основных состояниях: свободном (установленном) и занятом (сброшенном) и о трех операциях, выполняемых над ними:
· сбросить событие;
Событие в сброшенном состоянии считается занятым. цвета). Опущенный флаг (или выключенная лампа) означают, что такси занято. Любой поток, имеющий доступ к событию, может сбросить его, независимо от того, какой поток это событие устанавливал.
· установить (иногда — послать) событие;
Установленное (посланное) событие считается свободным. Как только событие освобождается, все ожидающие его потоки могут возобновить свое исполнение (см. сноску). Устанавливать событие может также любой поток.
· дождаться события;
Так как сброс и установка событий происходит в любой момент времени, независимо от предыдущего состояния события, то приходится вводить специальную операцию — дождаться освобождения объекта.
Эти особенности выделяют события в особую категорию синхронизирующих объектов. Рассмотренные ранее критические секции и объекты исключительного владения позволяют осуществить монопольный доступ к какому–либо ресурсу или объекту данных, в то время как события определяют некоторые условия, после которых возможно выполнение тех или иных операций.
Пример. Возвращаясь к примеру с глобальной кучей — для работы с ней необходимо создать составной синхронизирующий объект. Пример такого объекта можно найти в книге “Windows для профессионалов” Джеффри Рихтера. естественно, логика построения объекта одинакова и в рассматриваемом случае, что позволяет детально сравнить несколько близких решений и заострить внимание на некоторых “мелочах”. Сейчас мы рассмотрим только “скелет” такого объекта и основные правила работы с ним. Позже, после рассмотрения функций Win32 API, рассмотрим конкретную реализацию этого составного объекта и сравним ее с чрезвычайно похожим объектом, приведенным в книге Рихтера.
Сначала попробуем составить наличие хотя–бы одного читателя исключает для писателей возможность доступа к данным.
Из этих соображений следует наличие:
· Критической секции или объекта исключительного владения для синхронизации потоков–писателей. Выбор одного из этих объектов определяется необходимостью исключительного доступа только одного потока–писателя к данным. Удобно также, что освободить секцию или mutex может только тот поток, который его занял. В рассматриваемом примере будем использовать объект mutex, для большей схожести с Рихтером (это позволит подчернуть несколько нюансов в разработке такого объекта).
· События, переходящего в занятое состояние при наличии хотя–бы одного читателя. В данном случае целесообразно выбрать событие, которое будет сбрасываться в занятое состояние при появлении первого потока–читателя и устанавливаться в свободное последним читателем (последним из числа тех, кто пытается осуществить чтение одновременно с другими, но не вообще последнего).
· Счетчика числа потоков–читателей, осуществляющих одновременный доступ. Нулевое состояние. При уменьшении счетчика проверяется результат — если он 0, то событие устанавливается в свободное состояние.
Можно примерно описать структуру такого объекта (назовем его NEWSWMRG, по сравнению с объектом SWMRG, рассматриваемым у Рихтера — S
ingle W
riter M
ulti R
eader G
uard). Эта структура должна быть описана примерно так:
struct NEWSWMRG {
СОБЫТИЕ НЕТ_ЧИТАТЕЛЕЙ;
СЧЕТЧИК ЧИСЛО_ЧИТАТЕЛЕЙ;
объект_ИСКЛЮЧИТЕЛЬНОГО_ВЛАДЕНИЯ ЕСТЬ_ПИСАТЕЛИ;
};
Для работы с ней надо будет выделить четыре специальных функции (инициализацию и удаление этого объекта пока не рассматриваем): две функции, используемые потоками–читателями для получения доступа к данным и для обозначения конца операции чтения, а также две аналогичных функции для потоков–писателей.
void RequestWriter( NEWSWMRG* p ) {
// дождаться разрешения для писателя
Захватить объект ЕСТЬ_ПИСАТЕЛИ;
// если объект получен во владение — других писателей больше нет
// и пока мы его не освободим — не появятся.
Дождаться события НЕТ_ЧИТАТЕЛЕЙ;
// если событие установлено — читателей также нет
}
void ReleaseWriter( NEWSWMRG* p ) {
// после изменения данных разрешаем доступ другим писателям и читателям
Освободить объект ЕСТЬ_ПИСАТЕЛИ;
}
void RequestReader( NEWSWMRG* p ) {
// дождаться разрешения для читателя — убедиться, что нет писателей
// для этого можно захватить объект ЕСТЬ_ПИСАТЕЛИ и сразу освободить его
// захват пройдет только тогда, когда писателей нет.
Захватить объект ЕСТЬ_ПИСАТЕЛИ;
// реально надо не только убедиться в отсутствии писателей, но и
// увеличить счетчик и при необходимости сбросить событие НЕТ_ЧИТАТЕЛЕЙ
if ( ЧИСЛО_ЧИТАТЕЛЕЙ == 0 ) Сбросить событие НЕТ_ЧИТАТЕЛЕЙ в занятое;
ЧИСЛО_ЧИТАТЕЛЕЙ++;
// а вот теперь можно смело освобождать объект ЕСТЬ_ПИСАТЕЛИ — во время
// работы читателя достаточно иметь сброшенное событие НЕТ_ЧИТАТЕЛЕЙ Освободить объект ЕСТЬ_ПИСАТЕЛИ;
}
void ReleaseReader( NEWSWMRG* p ) {
// после считывания данных уменьшаем счетчик и разрешаем доступ писателям
// при достижении нулевого значения счетчика.
—ЧИСЛО_ЧИТАТЕЛЕЙ;
if ( ЧИСЛО_ЧИТАТЕЛЕЙ == 0 ) Установить событие НЕТ_ЧИТАТЕЛЕЙ в свободное;
}
естественно, это еще не рабочая схема, а только намек на нее. Полностью обсудим некоторые особенности при рассмотрении функций Win32 API. На первый взгляд виден небольшой “прокол” — в функции ReleaseReader счетчик сначала уменьшается, а только потом происходит проверка его значения и установка события при необходимости. Однако возможен (хотя и очень маловероятен) случай, когда поток будет прерван для выполнения операций другими потоками где–то между уменьшением счетчика и установкой события. В это время другие потоки могут изменить значение счетчика и событие будет установлено тогда, когда этого делать уже не следует.
Выйти из этой ситуации можно разными путями — либо добавлением еще одного объекта исключительного владения или критической секции для упорядочивания операций со счетчиком, либо другими способами. Для разбирательства с этими альтернативными способами следует рассмотреть синхронизацию с группой объектов.
[1]
Возможны такие объекты, хотя это не типичный случай, когда читатели не конфликтуют с писателями. Тогда в ситуациях 2 и 3 следует разрешать доступ.
[2]
В Win32 API существуют специальные механизмы, позволяющие возобновлять исполнение только одного потока при освобожении события. Однако, по сравнению с другими операционными системами, скажем OS/2, такое http://wpgrabbestrefedu.loc/2019/02/14/utchebnaya-rabota-laboratornaya-rabota-informatika-4/
Металургійний технікум ЗДІА
„РОБІТНИЧЕ СЕРЕДОВИЩЕ
MS
ACCESS
. ВІКНА, МЕНЮ І ПАНЕЛІ ІНСТРУМЕНТІВ
MS
ACCESS
”
Зв
іт з практичної роботи №1
Виконав
Ст. Гр. ОМП – 04 1/9
Перевірив
Викладач Терьохіна Л.Д.
Запоріжжя 2005 – 2006
отчет по практической работе №1
Тема: Рабочая среда MSAccess. окна, меню и панели инструментов MSAccess.
Так смотрится рабочее окно MSAccess.
Мы работали с системой управления базой данных (СУБД): при открытии либо разработке базы данных (БД) в окне Access возникает окно БД. В области заголовка БД представлено наименование и формат БД. В левой части окна БД представлена панель объектов:
1) Таблицы – главные объекты БД, хранят структуру БД (поля их типы и характеристики, и сами данные).
2) Запросы – эти объекты служат для извлечения данных из таблиц и предоставлению их юзеру в комфортном виде.
3) Формы – это средства для ввода данных. Формы предоставляют юзерам лишь те поля, которые ему заполнять положено.
4) отчеты – по своим свойствам и структуре отчёты почти во всем похожи на формы, но предусмотрены лишь для вывода данных на печатающее устройство.
5) Странички. Странички доступа к данным. Это спец. объекты баз данных реализованные в СУБД Access 2000.На физическом уровне – это особенный объект выполненный в коде HTML, размещённый на WEB – страничке и передаваемый клиенту совместно с ней.
6) Макросы – 7) Модули. Макросы состоят из последовательности внутренних установок СУБД. Модули делают средствами наружного языка программирования.
„ОСНОВНІ РЕЖИМИ РОБОТИ З ТАБЛИЦЯМИ. СТВОРЕННЯ ТАБЛИЦЬ. ВИЗНАЧЕННЯ ПОЛІВ ТАБЛИЦЬ
”
Зв
іт з практичної роботи №2
отчет по практической работе №2.
Тема. Главные режимы работы с таблицами. Создание таблиц.
Порядок сотворения БД:
1) Сделать БД под собственной фамилией:
Запуск Программки Access.
2) Избрать переключатель «Новенькая БД ОК»
3) Избрать окно «Файл новейшей БД»
4) Переименовать его как БД_Билый.
5) Сохранить файл в папке ОМП – 04 1/9.
6) Создаю таблицу в режиме конструктора:
7) Сохраняю как продукты. Опосля нажатия клавиши сохранить возникает окно с вопросцем: «Создавать индексное поле?», нажимаю на клавише «НЕТ»
8) Создаю таблицу путём ввода данных:
9) Создаютаблицу „Конторы” в режиме конструктора:
10) Создаютаблицу «Заказы» в режиме конструктора:
11) Создаюпервичныеключи в таблицеТовары (поле КодТовара) и в таблице Конторы (поле КодФирмы). Делаю схему данных из таблиц продукты, Конторы, Заказы и устанавливаю меж ними связь:
„
СТВОРЕННЯ ПЕРВ
І
СНИХ
КЛЮЧЕЙ ТА ЗВ
”
ЯЗКІВ”
Зв
іт з практичної роботи №
3
отчет по практической работе №3
Тема. Создание первичных ключей и связей.
В реляционных базах данных меж таблицами инсталлируются дела.
Это означает, что две и наиболее таблицы могут вместе употреблять одни и те же сведения. дела инсталлируются путём связи неповторимого поля (именуемого первичным) в одной таблице, с подходящим полем (именуемым наружным ключом) во 2-ой таблице.
Если поле является главным полем, то любая запись таблицы в этом поле обязана иметь неповторимое
1. Отношение «Один – к – одному» запись одной таблицы может иметь только одну связанную – запись в иной таблице:
2. Отношение «Один – ко — почти всем» — запись одной таблицы может иметь огромное количество связанных записей в иной таблице:
3. При отношении «Почти все – ко — почти всем» огромное количество записей одной таблицы может иметь огромное количество связанных записей в иной таблице:
„СТВОРЕННЯ ПРОСТОГО ЗАПИТУ ЗА ДОПОМОГОЮ МАЙСТРА ЗАПИТІВ. ЗМІНА ЗАПИТУ ЗА ДОПОМОГОЮ КОНСТРУКТОРА ЗАПИТУ”
Зв
іт з практичної роботи №4
отчет по практической работе №4
Тема: Создание обычного запроса при помощи мастера запросов. Изменение запроса при помощи конструктора запросов.
порядок выполнения работы:
1. Открываю свою базу данных БД_Гусев.
2. Запускаю мастер обычных запросов.
3. Выбираю из таблицы «Продукты» поля «КодТовара», «Наименование», «Стоимость».
4. Результаты запроса:
5. Таковой вид имеет запрос в режиме конструктора:
6.Режим SQL имеет вид:
SELECT продукты. КодТовара, Продукты. Наименование, Продукты. Стоимость, продукты
FROM Продукты;
7.Открываю запрос конструктором и убираю вывод на экран поля «КодТовара», сортирую по возрастанию поле «Наименование». Запустил запрос на выполнение.
Итог запроса:
Режим SQL имеет вид:
SELECT продукты. Наименование, Продукты. Стоимость, Продукты
FROM продукты
ORDERBY Продукты. Наименование;
8. Открываю запрос конструктором и сортирую «Наименование» по убыванию. Запускаю запрос на выполнение.
Итог запроса:
Режим SQL имеет вид:
SELECT продукты. Наименование, Продукты. Стоимость
FROM Продукты
ORDERBY продукты. Наименование DESC;
„СТВОРЕННЯ ЗАПИТУ З ФІЛЬТРОМ І ЗМІНА ЗАПИТУ”
Зв
іт з практичної роботи №
5
отчет по практической работе №5
Тема: Создание запроса с фильтром и изменение запроса
порядок выполнения работы:
1.Формирую при помощи конструктора последующий запрос:
Из таблицы Продукты добавляю: КодТовара, Наименование и Стоимость
Из таблицы Заказы: количество.
Запускаю запрос на выполнение.
Итог запроса:
2.Открываю сделанный запрос конструктором
3. Ставлю условия отбора Стоимость <2000,и опосля пуска запроса в таблице возникает лишь те продукты стоимость, которых меньше 2000.
4.Ставлю условия отбора стоимость <2000 и количество >5. Опосля пуска запроса в таблице остались лишь те продукты, стоимость которых <2000 и количество >5.
5.Выставляю Условия отбора Стоимость <2000 либо количество >5.
6. Выставляю условие отбора > [Укажите наибольшее количество], опосля пуска запроса возникает таблица с вопросцем «Укажите наибольшее количество».
Опосля введенных чисел 3 и 8 в запросе остались продукты MAX количество которых, соответственно 3 и 8.
„ВИКОРИСТАННЯ ВИРАЖЕНЬ У ЗАПИТАХ”
Зв
іт з практичної роботи №6
порядок выполнения работы:
1.Открываю свою базу данных.
2.Выбираю объект Запросы.
3.Запускаю конструктор запросов, добавляю таблицы продукты и Заказы.
4.Из таблицы Продукты избрать поля: Наименование и Стоимость.
Из таблицы Заказы поле: количество.
Сформировал вычисляемые поля:
Стоимость: ([Цена]*[количество])
Стоимость со скидкой: ([Цена]*[количество]) – ([Цена]*[Количество]*0.5)
5. Запускаю запрос на выполнение.
Возникла таблица продуктов со собственной стоимостью и со стоимость со скидкой.
6.Оператор SQL:
SELECT продукты. Наименование, Продукты. Стоимость, Заказы. количество, ([Цена]*[количество]) AS Стоимость, ([Цена]*[количество]) – ([Цена]*[количество]*0.5) AS [Стоимость со скидкой]
FROM ТоварыINNER JOIN ЗаказыON продукты. [КодТовара]=Заказы, КодТовара;
„АВТОМАТИЧНЕ СТВОРЕННЯ ФОРМИ НА ОСНОВІ ТАБЛИЦІ ЧИ ЗАПИТУ”
Зв
іт з практичної роботи №7
отчет по практической работе №7
Тема: Автоматическое создание формы на базе таблицы либо формы.
порядок выполнения работы:
1. Открываю свою базу данных.
2. Выбираю объект БД Таблицы.
3. Выбираю таблицу Конторы.
4. Делаю щелчок по кнопочке и создаю объект: автоформа.
Возникает Автоформа в столбец с именованием ФИРМЫ.
5. Просматриваю все записи таблицы ФИРМЫ.
6. Добавляю несколько записей.
7. Выполняю последующие конфигурации:
— добавляю 3 записи (выдумал их без помощи других);
— удаляю 2 записи из ранее добавленных;
— Изменяю в 3 записях данные (адресок и телефон).
Конструктора 8. Сохраняю форму с именованием ФИРМЫ_Автоформа1.
9. Открываю форму ФИРМЫ_Автоформа1 в режиме Конструктора.
При помощи клавиш панели форматирования изменяю:
— цвет заливки полей;
— Цвет текста;
— Цвет линий;
— Толщину полосы;
— Стиль дизайна.
В итоге выполнения вышеуказанных работ Форма приняла яркий вид. Разукрашивание Формы нужно для того, чтоб длительно не находить подходящий элемент.
10. Просматриваю Форму в режиме формы и в режиме Таблицы.
11. Открываю форму ФИРМЫ_Автоформа1 в режиме Конструктора и добавляю разделы заголовок/примечание. Для этого избрал меню ВИД – заголовок/примечание.
12. В области Заголовок вставляю заглавие формы. Для этого выполняю: выбираю элемент Надпись на панели инструментов и щелкнуть в области ЗАГОЛОВОК и протянуть указатель мыши при нажатой левой кнопочке мыши. Было вставлено пустое поле. Ввожу последующий текст ВВОД ДАННЫХ В ТАБЛИЦУ ФИРМЫ.
Форматирую размер букв «16», и цвет текста «Зелёный». Помещаю по центру.
13. В области примечание вставляю этим же образом текст: Работа студента ОМП – 04 Гусева Александра.
МАЙСТЕР ФОРМ. ПАРАМЕТРИ РОБОТИ З ФОРМАМИ”
Зв
іт з практичної роботи №
8
отчет по практической работе №8
Тема: Мастер форм. характеристики работы с формами.
Порядок выполнения работы:
1. Открываю свою БД
2. Выбираю объект БД Формы.
3. Запускаю программку «Создание формы при помощи мастера»
4. На первой страничке мастера выбираю все поля таблицы продукты и все поля, исключая КодФирмы, таблицы Заказы и нажимаю клавишу Дальше.
5. На 2-ой страничке Мастера избрать вид
6. На третьей страничке Мастера избрать наружный вид подчинённой формы Табличный.
7. На четвёртой страничке мастера избрать стиль формы.
8. На крайней страничке Мастера указать имя формы «Товары1_Заказы». Надавить клавишу ГОТОВО.
9. Привести в отчёте вид формы:
10. Выполняю последующие конфигурации:
а) Добавляю одну запись в главную таблицу продукты и несколько записей в подчиненную таблицу Заказы;
б) Удаляю запись в подчиненной таблице Заказы;
в) Удаляю запись в главной таблице продукты, если есть подчиненные записи в таблице Заказы.
11. Открываю форму в режиме конструктора.
а) В области заголовка добавляю заголовок формы ФОРМА ГЛАВНЫЙ – ПОДЧИНЕННЫЙ;
б) В области примечания добавляю набросок.
«
СТВОРЕННЯ ФОРМИ В РЕЖИМІ КОНСТРУКТОРА
»
Зв
іт з практичної роботи №
9
отчет по практической работе №9
Тема: Создание формы в режиме конструктора.
порядок выполнения работы:
1. Открываю свою Базу Данных.
2. Выбираю объект БД Формы и щёлкаю по кнопочке Сделать.
3. В окне Новенькая Форма выбираю конструктор, а в поле «Изберите в качестве источника данных таблицу либо запрос» избрал таблицу Заказы. Щёлкнул по кнопочке ОК. Был открыт пустой бланк конструктора и перечень полей таблицы заказы.
4. Выделяю все поля в таблице в таблице Заказы и перетягую все поля в область данных Конструктора(производится при нажатой левой кнопочке мыши)
5. Выполняю форматирование полей:
а) Меню формат -> ВЫРОВНЯТЬ -> ПО УЗЛАМ СЕТКИ;
б) Меню формат -> ВЫРОВНЯТЬ -> ПО ЛЕВОМУ КРАЮ;
в) Меню формат -> ИНТЕРВАЛ ПО ВЕРТИКАЛИ -> УВЕЛИЧИТЬ(пару раз);
г) Меню формат -> ИНТЕРВАЛ ПО ВЕРТИКАЛИ -> СДЕЛАТЬ РАВНЫМ.
6. Щёлкаю по полю КодТовара, вызываю характеристики, выбираю вкладку Данные, и свойство доступа изменяю на «нет». Поле КодТовара посерело и сделалось труднодоступным для допуска.
7. Щёлкаю по кнопочке в левом верхнем углу(в бланке конструктора), вызываю характеристики формы, выбираю вкладку данные, свойство разрешить удаление изменяю на «нет». Перехожу в режим формы. Попробовал удалить запись, но ничего не вышло.
8. Перехожу в режим конструктора. Щёлкаю на вольном поле справа. Выбираю меню Вставка -> элемент activeX -> в поле «изберите элемент ActiveX» выбираю «отран управления Календарь» И щёлкаю по кнопочке ОК. Добавился Календарь.
Щёлкаю мышкой по объекту Календарь, вызываю характеристики, выбираю вкладку Данные, свойство «данные» выбираю поле ДатаПокупки. Закрываю характеристики.
]]>