Давайте представим себе некоторую магистраль(дорогу) от точки A до точки B по которой все время ездят разные автомобили. У магистрали только две точки - вход и выход, ответвлений нет. Кроме того она однополосная. Если бы она была двухполосной, мы могли бы просто представить бы ее как две независимыемые магистрали и считали бы каждую из них отдельной.
Итак, каждая машина может заезжать на магистраль[Enter] спустя некоторое время покидать ее[Leave]. Кроме того магистраль может быть ограниченной по колочиству машин, которое она в себе содержит(MaximumEntries).
Кроме магистрали есть еще и ремонтники. Они могут блокировать магистраль(Lock) и разблокировать ее(Unlock).
Блокировка магистрали заключается в том что
а) сначала закрывается вход
б) ожидается пока все машины "съедут" с магистрали.
И только после этого магистраль закрывается. При этом машины, которые хотят попасть на магистраль ждут некоторое время, пока она закончится ремонт и магситраль откроется. У этого ожидания есть два вариант:
а) Дорогу отремантирует и магистраль откроется, тогда машина заедет на магситраль(попытка входа будет успешной)
либо
б) Таймаут ожидания истечет до того как магистраль отремонтируют и тогда машина развернется обратно(и попытка входа провалится).
Где такое может понадобится? Ну положим естьь база со сложно зависимыми объектами, при чем эта база в основном читается пользователями. И положим нельзя допустить что бы то время, как какойто пользователь юзает базу для чтения, ктото ее изменил. В таком случае, пользователи "читающие" базу будут "машинами", а те службы, которые будуит ее периодически изменять - "ремотниками".
Или скажем некоторый объект, который асинхронным образом юзают разные потоки, и для которого есть еще и другие, "технические" потоки, которые периодически осуществляют запись на диск. Очевидно, что в этом случае для записи информации надо дождаться пока все рабочие потоки не закончат свою текущую работу с объектом, то есть пока они не "освободят" магистраль для проведления ремонтных работ.
О реализации. Делалась в торопях, и особо не тестировалась. Кроме того, возможно есть иные пути для реализации такой вот дороги. Буду рад услышать любую критику по этому поводу. Учитывая, что в этом деле я полный нуб, возможно так же существование некоторого стандартного объекта синхронизации. Если такой имеется, скажите мне об этом.
- Код: Выделить всё
' Date: 13 october 2006
' Author: ANDLL, Web: http://danasoft.ru
' Class DANAsoft.General.Synchronization.MultythreadWay
Namespace DANAsoft.General.Synchronization
Public Class MultythreadWay
Public Const TIMEOUT_DEFAULT As Long = 1000
Public MaximumEntries As Integer = -1
Dim mThreads As New Collections.Generic.List(Of Threading.Thread)
Dim mSyncLock As New Object
Public Function EnterWay(Optional ByVal uTimeOut As Long = TIMEOUT_DEFAULT) As Boolean
If Threading.Monitor.TryEnter(mSyncLock, uTimeOut) Then
Try
SyncLock mThreads
If mThreads.Count > MaximumEntries And MaximumEntries <> -1 Then
Throw New InvalidOperationException("The way is overflowed now")
Else
mThreads.Add(Threading.Thread.CurrentThread)
End If
End SyncLock
Finally
Threading.Monitor.Exit(mSyncLock)
End Try
Return True
Else
Return False
End If
End Function
Public Sub LeaveWay()
SyncLock mThreads
mThreads.Remove(Threading.Thread.CurrentThread)
End SyncLock
End Sub
Public Sub LockWay()
SyncLock mThreads
If mThreads.Contains(Threading.Thread.CurrentThread) Then
Throw New Exception("Thread, that entered way, can not lock it.")
End If
Threading.Monitor.Enter(mSyncLock)
End SyncLock
Do
SyncLock mThreads
If mThreads.Count = 0 Then Exit Do
Dim I As Threading.Thread
For Each I In mThreads
If Not I.IsAlive Then
mThreads.Remove(I)
Exit For
End If
Next
End SyncLock
Threading.Thread.Sleep(4)
Loop
End Sub
Public Sub UnlockWay()
Threading.Monitor.Exit(mSyncLock)
End Sub
End Class
End Namespace