.NET Thread不安全代码
我明白COM中多线程公寓和单线程公寓的区别。.NET Thread不安全代码
请参阅下面的代码:
'VB.NET
Imports Project1
Imports System.Threading
Public Class Form1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim t1 As New Thread(AddressOf PersonTest.Test2)
Dim t2 As New Thread(AddressOf PersonTest.Test2)
Dim t3 As New Thread(AddressOf PersonTest.Test2)
t1.Name = "Test1"
t2.Name = "Test2"
t3.Name = "Test3"
t1.Start()
t2.Start()
t3.Start()
End Sub
End Class
Public Class PersonTest
Public Shared Sub Test2()
Try
Dim c1 As Class1
c1 = New Class1
For test3 As Integer = 0 To 10000
For test As Integer = 0 To 10000
Dim test2 As Short = c1.Add(CShort(test))
If test2 <> test + 1 Then
MsgBox("Problem here")
End If
Next
Next
MsgBox("finished")
Catch ex As Exception
End Try
End Sub
End Class
Public Class Person
Public id As Integer
End Class
'VB6 - Project1.vbp,class1
Public Test2 As Integer
Public Function Add(ByVal TestParameter As Integer) As Integer
Test2 = TestParameter + 1
Add = Test2
End Function
基于我已阅读,我希望“MSGBOX(‘问题就在这里’)”出现,因为多个线程可以改变Person.ID的值了同步,但我已经测试了这个程序很多次,它从来没有发生过。我明白线程“没有任何保证”。上面的代码是否会在理论上造成问题?如果答案是否定的,那么如何修改代码来引发问题?我正在学习如何编写线程安全代码,为了做到这一点,我必须首先了解代码如何可能不安全。
VB6生成标记单元线程COM组件在注册表中。一个昂贵的词是“不是线程安全的”。您创建的线程位于MTA中,因为您没有调用Thread.SetApartmentState()。
首先,您实际上并没有测试线程不安全的代码,因为您在方法中将它分配为局部变量,所以每个线程都会获取自己的对象。局部变量存储在堆栈中,每个线程都有自己的堆栈。只有当多个线程都可以读写共享变量时,线程安全性才会受到影响。您将不得不在Form_Load()方法中创建对象,并将引用存储在表单类的成员中以便共享。
COM没有意识到你实际上没有线程问题。它会自动启动一个新线程,一个是STA为COM对象提供一个安全的家。您可以在Debug + Windows + Threads调试器窗口中看到这些线程。
它自动将工作线程对Add()函数的调用编组到该STA线程。根据公寓规则的要求。这很慢,你的代码应该需要一段时间。就像一个实验一样,在每个线程开始切换到STA之前调用SetApartmentState。现在,不再需要帮助器线程并且不需要编组,您将看到代码更快完成批次。
使用Class1的共享实例将是一个更好的测试。但是更新Test2变量仍然是线程安全的,因为它位于一个单元线程对象内。然而,它获得的实际值是随机的,无论线程上次更新它。
你的大部分问题似乎是多个线程没有更新一个值的oppertunity。
在每个线程中,您正在创建一个新实例Class1
,该实例有其自己的实例Test2
,因此您的每个线程都是唯一运行的线程。
你的代码更改为这将迫使它exibit你想要的问题,虽然我不知道这是否回答您的问题或不...
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim pt = New PersonTest
Dim t1 As New Thread(AddressOf pt.Test2)
Dim t2 As New Thread(AddressOf pt.Test2)
Dim t3 As New Thread(AddressOf pt.Test2)
t1.Name = "Test1"
t2.Name = "Test2"
t3.Name = "Test3"
t1.Start()
t2.Start()
t3.Start()
End Sub
Public Class PersonTest
Private _class As New Class1
Public Sub Test2()
Try
For test3 As Integer = 0 To 10000
For test As Integer = 0 To 10000
Dim test2 = _class.Add(test)
If test2 <> test + 1 Then
MsgBox("Problem here")
End If
Next
Next
MsgBox("Finished")
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
End Class
Public Class Person
Public id As Integer
End Class
Public Class Class1
'VB6 - Project1.vbp,class1
Public Test2 As Integer
Public Function Add(ByVal TestParameter As Integer) As Integer
Test2 = TestParameter + 1
Add = Test2
End Function
End Class
我假设你在多线程上调用它?我认为对MsgBox的调用必须在UI线程上(不是它影响线程问题) – Rob 2013-04-11 09:21:12
@Rob,代码显示在Form.Load处理函数中创建了三个线程。 – w0051977 2013-04-11 09:25:39
和VB6函数'添加'大概是inproc而不是STA? – Rob 2013-04-11 09:26:53