Имитатор Многопоточности




Рассмотрим проект MTDemo:

Проект содержит один модуль кода, в котором содержится две глобальных переменных:

' MTDemo - Multithreading Demo program

' Copyright © 1997 by Desaware Inc. All Rights Reserved

Option Explicit

Public GenericGlobalCounter As Long

Public TotalIncrements As Long

' Этот проект содержит одну форму - frmMTDemo1, которая содержит

' следующий код:

' MTDemo - Multithreading Demo program ' Copyright © 1997 by Desaware Inc. All Rights Reserved

Option Explicit

Dim State As Integer

' State = 0 - Idle

' State = 1 - Loading existing value

' State = 2 - Adding 1 to existing value

' State = 3 - Storing existing value

' State = 4 - Extra delay

Dim Accumulator As Long

Const OtherCodeDelay = 10

Private Sub Command1_Click()

Dim f As New frmMTDemo1

f.Show

End Sub

Private Sub Form_Load()

Timer1.Interval = 750 + Rnd * 500

End Sub

Private Sub Timer1_Timer()

Static otherdelay&

Select Case State

Case 0

lblOperation = "Idle"

State = 1

Case 1

lblOperation = "Loading Acc"

Accumulator = GenericGlobalCounter

State = 2

Case 2

lblOperation = "Incrementing"

Accumulator = Accumulator + 1

State = 3

Case 3

lblOperation = "Storing"

GenericGlobalCounter = Accumulator

TotalIncrements = TotalIncrements + 1

State = 4

Case 4

lblOperation = "Generic Code"

If otherdelay >= OtherCodeDelay Then

State = 0

otherdelay = 0

Else

otherdelay = otherdelay + 1

End If

End Select

UpdateDisplay

End Sub

Public Sub UpdateDisplay()

lblGlobalCounter = Str$(GenericGlobalCounter)

lblAccumulator = Str$(Accumulator)

lblVerification = Str$(TotalIncrements)

End Sub

Эта программа для моделирования многопоточного режима использует таймер и простой конечный автомат. Переменная State описывает пять команд, которые эта программа выполняет. State = 0 - неактивное состояние. State = 1 загружает локальную переменную глобальной переменной GenericGlobalCounter. State = 2 увеличивает на единицу локальную переменную. State = 3 запоминает результат в переменной GenericGlobalCounter и увеличивает переменную TotalIncrements (которая считает количество приращений переменной GenericGlobalCounter). State = 3 добавляет дополнительную задержку, представляющую собой время, затраченное на выполнение других команд в программе.

Функция UpdateDisplay обновляет три метки на форме, которые показывают текущее значение переменной GenericGlobalCounter, локального сумматора, и общего количества приращений.

Каждый сигнал таймера моделирует цикл ЦЕНТРАЛЬНОГО ПРОЦЕССОРА в текущем потоке. Если Вы запустите программу, то увидете, что значение переменной GenericGlobalCounter будет всегда точно равно переменной TotalIncrements, потому что переменная TotalIncrements показывает количество увеличений счетчика GenericGlobalCounter потоком.

Но что случится, когда Вы нажимаете кнопку Command1 и запустите второй экземпляр формы? Эта новая форма смоделирует второй поток.

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

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

Такая проблема может привести к появлению ресурсов, постоянно недоступных в системе, к объекту, блокируемому в памяти, или преждевременно освобожденному. Это может привести к сбоям приложения.

Этот пример был разработан, чтобы достаточно просто увидеть проблему, но попробуйте поэкспериментировать со значением переменной OtherCodeDelay. Когда опасный код относительно небольшой по сравнению со всей программой, проблемы появятся менее часто. Хотя это и звучит обнадеживающе, но истина состоит в следующем. Проблемы Многопоточного режима могут быть чрезвычайно неустойчивы и их трудно обнаружить. Это означает, что многопоточный режим требует осторожного подхода к проектированию приложения.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2020-04-01 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: