I know you all read 8 things you probably didn’t know about C#. But there’s a million things about threads you didn’t know and then some would be a nice title for a blogpost too.

It’s this little line that should draw your attention.

i = 1 is atomic (thread-safe) for an int but not long

And that is good to know (for 32-bit systems anyway).

But don’t mistake the above with this line.

i += 1

That line is not threadsafe.

You can easily verify that by doing this.

Imports System.Threading

Module Module1

    Private incre As New Incrementing

    Sub Main()
        For i = 1 To 10
            Dim t1 As New Thread(AddressOf count)
            t1.IsBackground = True
            t1.Start()
            Dim t2 As New Thread(AddressOf count)
            t2.IsBackground = True
            t2.Start()
        Next
        Console.ReadLine()
    End Sub

    Sub count()
        For i = 1 To 1000
            incre.Add()
            Thread.Sleep(1)
        Next
        Console.WriteLine(incre.Read())
    End Sub

    Public Class Incrementing
        Private i As Integer = 0

        Public Sub Add()
            i += 1
        End Sub

        Public Function Read() As Integer
            Return i
        End Function
    End Class
End Module

You would expect to get to 20000 here because you are doing 20000 time i += 1, right.

Well no.

18342

18359

18404

18437

18444

18444

18444

18473

18479

18490

18490

18491

18494

18514

18520

18520

18522

18525

18525

18527

this was one of the results I got.

Doesn’t make sense?

Well sure it does.

because i += 1 is actually 3 operations (at least).

Read i, add 1 to i and then store i. And I did not take that into account.

So at several points in time two or more threads might be reading the same value of i and thus we never get to 20000.

There are of course several ways around this.

We could synclock the i += 1 operation.

vbnet Public Sub Add() SyncLock lockobject i += 1 End SyncLock End Sub or we could use Interlocked.Increment(i)

vbnet Public Sub Add() Interlocked.Increment(i) End Sub And now the results are more inline with what I expected.

19857

19863

19877

19887

19902

19906

19932

19932

19941

19948

19955

19960

19967

19974

19989

19992

19995

19997

19999

20000