I know you all read [8 things you probably didn’t know about C#][1]. 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.

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

 [1]: http://damieng.com/