.NET多线程变量访问 [英] .NET multi-threaded variable access

查看:71
本文介绍了.NET多线程变量访问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆