• Иллюстрированный самоучитель по Visual Basic .NET

    Взаимная блокировка

    39 Public Class Knife
    40 Private Shared mKnifeAvailable As Boolean = True
    41 Private Shared mOwner As String ="Nobody"
    42 Private Readonly Property OwnsUtensi1() As String
    43 Get
    44 Return mOwner
    45 End Get
    46 End Property
    47 Public Sub GrabKnifetByVal a As Programmer)
    48 Console.WriteLine(Thread.CurrentThread.Name & _
    "trying to grab the knife.")
    49 Console.WriteLine(Me.OwnsUtensil & "has the knife.")
    50 Monitor.Enter(Me) 'SyncLock (aKnife)'
    51 If mKnifeAvailable Then
    52 mKnifeAvailable = False
    53 a.HasKnife = True
    54 mOwner = a.MyName
    55 Console.WriteLine(a.MyName&"just got the knife.waiting")
    56 Try
    Thread.Sleep(100)
    Catch e As Exception
    Console.WriteLine (e.StackTrace)
    End Try
    57 End If
    58 Monitor.Exit(Me)
    59 End Sub
    60 End Class
    61 Public Class Programmer
    62 Private mName As String
    63 Private Shared mFork As Fork
    64 Private Shared mKnife As Knife
    65 Private mHasKnife As Boolean
    66 Private mHasFork As Boolean
    67 Shared Sub New()
    68 mFork = New Fork()
    69 mKnife = New Knife()
    70 End Sub
    71 Public Sub New(ByVal theName As String)
    72 mName = theName
    73 End Sub
    74 Public Readonly Property MyName() As String
    75 Get
    76 Return mName
    77 End Get
    78 End Property
    79 Public Property HasKnife() As Boolean
    80 Get
    81 Return mHasKnife
    82 End Get
    83 Set(ByVal Value As Boolean)
    84 mHasKnife = Value
    85 End Set
    86 End Property
    87 Public Property HasFork() As Boolean
    88 Get
    89 Return mHasFork
    90 End Get
    91 Set(ByVal Value As Boolean)
    92 mHasFork = Value
    93 End Set
    94 End Property
    95 Public Sub Eat()
    96 Do Until Me.HasKnife And Me.HasFork
    97 Console.Writeline(Thread.CurrentThread.Name&"is in the thread.")
    98 If Rnd() < 0.5 Then
    99 mFork.GrabFork(Me)
    100 Else
    101 mKnife.GrabKnife(Me)
    102 End If
    103 Loop
    104 MsgBox(Me.MyName & "can eat!")
    105 mKnife = New Knife()
    106 mFork= New Fork()
    107 End Sub
    108 End Class
    

    Основная процедура Main (строки 4-16) создает два экземпляра класса Programmer и затем запускает два потока для выполнения критического метода Eat класса Programmer (строки 95-108), описанного ниже. Процедура Main задает имена потоков и запускает их; вероятно, все происходящее понятно и без комментариев.

    Интереснее выглядит код класса Fork (строки 17-38) (аналогичный класс Knife определяется в строках 39-60). В строках 18 и 19 задаются значения общих полей, по которым можно узнать, доступна ли в данный момент вилка, и если нет – кто ею пользуется. ReadOnly-свойство OwnUtensi1 (строки 20-24) предназначено для простейшей передачи информации.

    Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.