Why doesn't this code demonstrate the non-atomicity of reads/writes?

后端 未结 4 1019
不思量自难忘°
不思量自难忘° 2020-12-11 02:42

Reading this question, I wanted to test if I could demonstrate the non-atomicity of reads and writes on a type for which the atomicity of such operations is not guaranteed.

4条回答
  •  感情败类
    2020-12-11 03:17

    You might try getting rid of the 'dCopy = _d' and simply use _d in your assert.

    That way two threads are reading/writing to the same variable at the same time.

    Your current version makes a copy of _d which creates a new instance, all in the same thread, which is a thread safe operation:

    http://msdn.microsoft.com/en-us/library/system.double.aspx

    All members of this type are thread safe. Members that appear to modify instance state actually return a new instance initialized with the new value. As with any other type, reading and writing to a shared variable that contains an instance of this type must be protected by a lock to guarantee thread safety.

    However if both threads are reading/writing to the same variable instance then:

    http://msdn.microsoft.com/en-us/library/system.double.aspx

    Assigning an instance of this type is not thread safe on all hardware platforms because the binary representation of that instance might be too large to assign in a single atomic operation.

    Thus if both threads are reading/writing to the same variable instance you would need a lock to protect it (or Interlocked.Read/Increment/Exchange., not sure if that works on doubles)

    Edit

    As pointed out by others, on an Intel CPU reading/writing a double is an atomic operation. However, if the program is compiled for X86 and uses a 64 bit integer data type, then the operation would not be atomic. As demonstrated in the following program. Replace the Int64 with double and it appears to work.

        Public Const ThreadCount As Integer = 2
        Public thrdsWrite() As Threading.Thread = New Threading.Thread(ThreadCount - 1) {}
        Public thrdsRead() As Threading.Thread = New Threading.Thread(ThreadCount - 1) {}
        Public d As Int64
    
         _
        Sub Main()
    
            For i As Integer = 0 To thrdsWrite.Length - 1
    
                thrdsWrite(i) = New Threading.Thread(AddressOf Write)
                thrdsWrite(i).SetApartmentState(Threading.ApartmentState.STA)
                thrdsWrite(i).IsBackground = True
                thrdsWrite(i).Start()
    
                thrdsRead(i) = New Threading.Thread(AddressOf Read)
                thrdsRead(i).SetApartmentState(Threading.ApartmentState.STA)
                thrdsRead(i).IsBackground = True
                thrdsRead(i).Start()
    
            Next
    
            Console.ReadKey()
    
        End Sub
    
        Public Sub Write()
    
            Dim rnd As New Random(DateTime.Now.Millisecond)
            While True
                d = If(rnd.Next(2) = 0, 0, Int64.MaxValue)
            End While
    
        End Sub
    
        Public Sub Read()
    
            While True
                Dim dc As Int64 = d
                If (dc <> 0) And (dc <> Int64.MaxValue) Then
                    Console.WriteLine(dc)
                End If
            End While
    
        End Sub
    

提交回复
热议问题