Средства синхронизации потоков, критические секции и тупики

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

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

Только один процесс должен иметь возможность изменять и записывать значения глобальных переменных.

Для решения этой задачи могут использоваться простые средства – критические секции, обеспечивающие поочередный доступ к критическим участкам потоков одного процесса, и более сложные средства – Mutex ( mutually exclusive – взаимно- исключающий)-

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

В рассмотренном ниже приложении два потока увеличивают значение глобальной переменной Global от начального значения 100 на 1 при каждом выполнении цикла. Число повторений цикла каждого потока равно 12, результаты увеличения переменной Global выводятся на экран в виде двух списков ListBox.

При правильной работе приложения конечным значением переменной должно быть число 100+12+12=124. Однако без специальных мер такого значения получить в общем случае не удается, так как потоки " мешают ” друг другу.

Критические секции обеспечивают поочередный доступ потоков к критическим участкам программы . Для этого в начале критического участка вызывается функция

EnterCriticalSection ( имя секции) , а в конце – функция

LeaveCriticalSection ( имя секции).

Порядок выполнения работы

1. Создать приложение в соответствии с приведенным ниже текстом, в котором создаются 2 потока одного процесса, выполняющиеся с критическими секциями.

Приложение использует 1 Button, 2 ListBox , 1 CheckBox. При установке (включении) критических секций конечным результатом работы приложения должно быть значение глобальной переменной, равное 124.

2. Проверить работу мьютекса. Снять символы комментариев, поставить их на операторах использования критических секций и запустить приложение сначала с критическими секциями (вместо них теперь используется мьютекс), а затем без них.

3. Добавить возможность изменения приоритетов потоков. Запустить приложение с различными приоритетами потоков. Ответить на вопрос: как влияет изменение приоритетов потоков на результаты выполнения приложения.

unit Critsec;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

StdCtrls;

type

TForm1 = class(TForm)

Button1: TButton; ListBox1: TListBox; ListBox2: TListBox;

CheckBox1: TCheckBox;

procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure Button1Click(Sender: TObject);

end;

var

Form1 : TForm1;

crits : boolean;

sect1 : TRTLCriticalSection;

global: word;

// 2 // hmut : thandle;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);

begin

initializeCriticalSection(sect1);

// 2 // hmut := createmutex(nil,true,nil);

end;

procedure TForm1.FormDestroy(Sender: TObject);

begin

DeleteCriticalSection(sect1);

//2// closehandle(hmut);

end;

function Thr1 (p:pointer):longint; stdcall;

var i,j : integer;

begin

form1.listbox1.items.clear;

for j:=1 to 12 do

begin

if crits then

EnterCriticalSection (sect1);

//2// waitforsingleobject(hmut,infinite);

sleep(10);

i:=global; i:=i+1;

form1.listbox1.items.add(intToStr(i));

global:=i;

if crits then

LeaveCriticalSection(sect1);

//2// releasemutex(hmut);

end;

end;

function Thr2 (p:pointer):longint; stdcall;

var i,j : integer;

begin

form1.listbox2.items.clear;

for j:=1 to 12 do

begin

if crits then

EnterCriticalSection (sect1);

//2// waitforsingleobject(hmut,infinite);

sleep(7);

i:=global; i:=i+1;

form1.listbox2.items.add(intToStr(i));

global:=i;

if crits then

LeaveCriticalSection(sect1);

//2// releasemutex(hmut);

end;

end;

procedure TForm1.Button1Click(Sender: TObject);

var thrid : dword;

thrh1,thrh2: thandle;

begin

global:= 100;

if CheckBox1.Checked then crits:= true

else crits:= false ;

thrh1:=CreateThread(nil,0,@Thr1,nil,0,thrid);

thrh2:=CreateThread(nil,0,@Thr2,nil,0,thrid);

end;

end.

4. Создать приложение, аналогичное заданию п.1, используя класс Tthread Delphi и проверить его работу. Сравнить полученные результаты с результатами, полученными в п.2.

5. Добавить в один из потоков разработанных в п.1 приложений операторы, завершающие выполнение одного из потоков после прохождения 5 циклов. Выполнить приложения, отследить поведение второго потока приложений.

6. Переписать разработанные приложения с использованием семафора и события и проверить правильность их работы.

7. Добавить в один из потоков разработанных приложений операторы, завершающие выполнение одного из потоков после прохождения 5 циклов. Выполнить приложения, отследить поведение второго потока приложений.

8. Используя материал лекций, разработать приложение с 2 потоками, попадающими в тупик в процессе выполнения. Параметры потоков (длительность выполнения их участков) должны задаваться при помощи ввода с клавиатуры. Проверить работу приложения при многократном запуске с различными значениями параметров.

ОТЧЕТ О РАБОТЕ

Должен быть представлен в виде текстов разработанных в приложений и письменного ответа на вопросы:

1. В чем состоит отличие критического участка от критической секции?

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

3. Как проявлялись последствия тупика потоков приложения? Всегда ли потоки при неизменных значениях параметров оказывались в тупике?

4. Использование каких средств синхронизации может приводить к тупику?

5. Распознает ли MS Windows состояние тупика потоков?

Лабораторная работа № 7

Наши рекомендации