Atomic Counters in Visual Basic .NET

Here’s the translation of the atomic counters example from Go to Visual Basic .NET:

In Visual Basic .NET, we can use the Interlocked class to perform atomic operations on variables that are shared by multiple threads. This is similar to the sync/atomic package in other languages. Let’s look at an example of using atomic counters:

Imports System
Imports System.Threading
Imports System.Threading.Tasks

Module AtomicCounters
    Sub Main()
        ' We'll use a long to represent our (always-positive) counter.
        Dim ops As Long = 0

        ' We'll use a CountdownEvent to wait for all tasks to finish.
        Dim countdown As New CountdownEvent(50)

        ' We'll start 50 tasks that each increment the counter exactly 1000 times.
        For i As Integer = 0 To 49
            Task.Run(Sub()
                         For c As Integer = 0 To 999
                             ' To atomically increment the counter we use Interlocked.Increment.
                             Interlocked.Increment(ops)
                         Next
                         countdown.Signal()
                     End Sub)
        Next

        ' Wait until all the tasks are done.
        countdown.Wait()

        ' It's safe to read 'ops' here because all tasks have finished.
        Console.WriteLine("ops: " & ops)
    End Sub
End Module

In this Visual Basic .NET code:

  1. We use a Long variable ops to represent our counter. This is equivalent to the uint64 used in other languages.

  2. Instead of a WaitGroup, we use a CountdownEvent to wait for all tasks to complete.

  3. We create 50 tasks using Task.Run(), which is similar to launching goroutines in other languages.

  4. Inside each task, we use Interlocked.Increment(ops) to atomically increment the counter. This is equivalent to the Add method used in other atomic implementations.

  5. After creating all tasks, we wait for them to complete using countdown.Wait().

  6. Finally, we print the value of ops.

To run this program, save it as AtomicCounters.vb and compile it using the Visual Basic compiler:

$ vbc AtomicCounters.vb
$ AtomicCounters.exe
ops: 50000

We expect to get exactly 50,000 operations. If we had used a non-atomic integer and incremented it with ops += 1, we’d likely get a different number, changing between runs, because the tasks would interfere with each other.

The Interlocked class in Visual Basic .NET provides atomic operations that are safe for use in multithreaded scenarios. It ensures that the increment operation is performed as a single, indivisible unit, preventing race conditions and ensuring thread-safety.

Next, we could look at other synchronization primitives in Visual Basic .NET, such as the SyncLock statement, which is similar to mutexes in other languages.