我已经阅读了很多关于这个主题的帖子,但是当从多个线程调用C#处理方法中的参数时,我仍然有点模糊。
我有一系列需要从大约60多个线程调用的实用程序方法。这是一个每天为大约20,000-30,000名患者下载患者数据的过程。在大多数情况下,方法看起来像这样。
Public Static SomeClass
{
public static string StringToSQLBool(string s)
{
if (s.Trim() == "")
{
return "Null";
}
else
{
if (s.ToLower() == "true")
{
return "1";
}
{
return "0";
}
}
}
public static string DateToSQLAnsiStr(string ADate)
{
try
{
if (ADate.Trim() != "")
{
DateTime d = Convert.ToDateTime(ADate);
return "{d '" + d.Year.ToString() + "-" +
d.Month.ToString().PadLeft(2, '0') + "-" +
d.Day.ToString().PadLeft(2, '0') + "'}";
}
else
{
return "Null";
}
}
catch
{
return "Null";
}
}
}
据我所知,只要参数在调用线程的单数方法中使用,就会被认为是安全的。
这些线程是否安全而不锁定?
答案 0 :(得分:3)
在线程中尝试操纵(或在一个中操作并在另一个中访问)相同的对象 时,线程是一个问题。通过访问对象的“名称”无关紧要。
使用术语“变量”来讨论类成员是一种不太理想的方式,特别是在上下文中,引用字段。这是关键的区别:局部变量,包括参数,一次只能由两个线程 1 访问。
逐字回答问题:“参数始终是线程安全的”,尽管它们评估为的对象可能不是。
但是,在示例代码中,仅使用 不可变对象 2 :
String +
运算符返回一个 new 字符串,它是两者的串联,这是新的String结果,它被重新赋值给local(参数)变量。同样的逻辑适用于DateTime。
因此,发布的代码存在 no 线程问题;因为不管局部变量或参数如何,都没有相同对象的共享操作(或操作和访问)。
1 对线程绑定变量(包括参数)的访问通常必须在线程上下文中视为 field 访问。这是因为C#编译器在幕后合成/创建一个隐藏对象,然后对其进行操作以存储闭包状态。
2 如果某个对象在创建后无法操作,则会将其视为不可变类型,并且本质上是线程安全的。字符串属于这一类。 (只有在完全构造对象后才能保证不可变对象的线程安全。)
答案 1 :(得分:2)
对来自不同线程的方法的每次调用都有自己的堆栈。传递给方法的值类型存储在堆栈中。传递给方法的引用类型的指针存储在堆栈中。无论哪种方式,它都在堆栈上。
因为每个线程都有自己的堆栈,所以多次调用来自不同线程的方法不会覆盖"#34;覆盖"彼此'参数。
据我所知,只要参数在调用线程的单数方法中使用,就会被认为是安全的。
有一种倾向,像律师一样选择这样的陈述(特别是因为它涉及听起来像医疗记录。)你的理解是正确的。
我并不是说像律师一样挑选问题是错误的。细节很重要。但是你非常清楚地问了你的问题所以我明白你的意思。
我怎么说这个没有听起来有点光顾,因为你可能是一个非常有经验的程序员,这恰好是你第一次使用.NET专门处理多线程。请小心。我想到医疗记录是错误的人,声称被拒绝,或者因为线程错误而不小心接受化疗或性别重新分配,我感到非常震惊。我认为在这种情况下,社区应该非常积极地协助您处理所有多线程问题。
答案 2 :(得分:0)
标题中问题的答案是“可能;这取决于他们的类型。”