.NET多线程变量访问 [英] .NET multi-threaded variable access
问题描述
我有一个具有4个线程的应用程序. (GUI,控制器,生产者,消费者)
I have an application with 4 threads. (GUI, Controller, Producer, Consumer)
GUI是不言自明的.
The GUI is self-explanatory.
控制器在进行一些初始设置后启动生产者线程和使用者线程.
The controller starts the producer and consumer threads after some intial setup.
生产者创建项目并将其放置在环形缓冲区"中的空闲插槽中
The producer creates items and places them in a free slot in a "ring buffer"
使用者从环形缓冲区"中取出项目并将其写入磁盘.
The consumer takes items from the "ring buffer" and writes them to disk.
生产者创造商品的速度比消费者高得多.
The producer creates items at a much higher rate than the consumer.
消费者是IO繁重且受IO束缚的人.
The consumer is IO heavy and IO bound.
目前,我正在检查每个环形缓冲区插槽中的变量,以确定是否可以将其写入.
Currently I am checking a variable in each ring buffer slot to determine if it can be written to.
if Slot.Free then
Write Slot.Data To Disk
end if
我不是在使用锁/同步锁,而是在读/写插槽的"free"变量的值.我认为这是不正确的,即使它是易失性的读/写.有没有更好的方法来读取/写入此变量?变量的类型为整数",并且为0或1.
I am not using lock/synclock instead I'm just reading / writing the value of the slot's "free" variable. I don't believe that is correct even though it is a volatile read/write. Is there a better method to read/write this variable? The variable is of type "integer" and is either 0 or 1.
推荐答案
您提到使用环形缓冲区,但是(正确实现的)环形缓冲区将能够在不检查所有元素的情况下确定其是否已满,从而消除了对每个插槽中都有一个布尔值.
You mention using a ring buffer, but a (properly implemented) ring buffer would be able to determine if it's full without checking all it's elements, eliminating the need for a boolean in each slot.
我不习惯VB.NET,但这应该是环形缓冲区的有效(如果是粗略的)实现,该环形缓冲区在相应的写入/读取操作已满/为空时会阻塞.
I'm not used to VB.NET, but this should be a working (if crude) implementation of a ring buffer that blocks when it's full / empty on respective write / read actions.
Friend Class RingBuffer(Of T)
Private _slots() As T
Private _head As Integer
Private _tail As Integer
Private _readableSlots As Semaphore
Private _readLock As Object
Private _writableSlots As Semaphore
Private _writeLock As Object
Public Sub New(ByVal size As Integer)
ReDim _slots(size - 1)
_head = 0
_tail = 0
_readLock = New Object
_writeLock = New Object
_readableSlots = New Semaphore(0, size)
_writableSlots = New Semaphore(size, size)
End Sub
Public Function Dequeue() As T
Dim item As T
_readableSlots.WaitOne()
SyncLock _readLock
item = _slots(_head)
_head = (_head + 1) Mod _slots.Length
End SyncLock
_writableSlots.Release()
Return item
End Function
Public Sub Enqueue(ByVal item As T)
_writableSlots.WaitOne()
SyncLock _writeLock
_slots(_tail) = item
_tail = (_tail + 1) Mod _slots.Length
End SyncLock
_readableSlots.Release()
End Sub
End Class
一旦有了,您的生产者和消费者就可以变得愚蠢:)但是,如果您有多个消费者,则不能完全保证按顺序处理商品:
Once you have that, your Producer and Consumer can be really dumb :) It's not exactly guaranteed that items are processed in-order if you have multiple consumers however:
Private _buffer As RingBuffer(Of Integer) = New RingBuffer(Of Integer)(5)
Private Sub Producer()
Dim i As Integer = 0
Do While True
_buffer.Enqueue(i)
i = i + 1
Loop
End Sub
Private Sub Consumer()
Do While True
Debug.WriteLine(("Consumer A: " & _buffer.Dequeue))
Thread.Sleep(1000)
Loop
End Sub
这篇关于.NET多线程变量访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!