Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 静态或非静态方法,线程安全性适用于类型而不是方法_C#_.net_Multithreading - Fatal编程技术网

C# 静态或非静态方法,线程安全性适用于类型而不是方法

C# 静态或非静态方法,线程安全性适用于类型而不是方法,c#,.net,multithreading,C#,.net,Multithreading,我有一段时间有这种困惑,静态方法实现线程是安全的,实例方法当然是线程安全的,如果我们给每个线程分配一个单独的实例,那么它们就不会干预,然后我意识到,线程安全更多的是类型而不是方法,它们本身不是内存分配,让我们举个例子: private static ConcurrentDictionary<int,int> cd; public static void Method1(int userid) { // Modify static object cd based on user

我有一段时间有这种困惑,静态方法实现线程是安全的,实例方法当然是线程安全的,如果我们给每个线程分配一个单独的实例,那么它们就不会干预,然后我意识到,线程安全更多的是类型而不是方法,它们本身不是内存分配,让我们举个例子:

private static ConcurrentDictionary<int,int> cd;

public static void Method1(int userid)
{
   // Modify static object cd based on userid key
}

public void Method2(int userid)
{
    // Modify static object cd based on userid key
}
私有静态ConcurrentDictionary cd;
公共静态void方法1(int userid)
{
//基于用户ID密钥修改静态对象cd
}
公共void方法2(int userid)
{
//基于用户ID密钥修改静态对象cd
}

本质上,当在运行时由提供不同用户ID的多个线程访问时,这两个方法之间没有区别。我已经测试过了,但想验证我的理解是否正确。

线程安全与类和类实例无关。这两种方法都可能以不安全的方式用于线程

但是通常像winforms控件这样的对象不能从其他线程访问它们的资源,因此它们会检查您是否从其他线程访问它们,并且您必须确保使用Invoke为该控件使用所需的线程

静态方法实现线程安全吗

不,如果它们修改共享数据,那么它们同样是非线程安全的。您的示例可能还可以,但这仅仅是因为共享数据本身是线程安全的,是一个不可变类型(
int
s)的
concurrentdirectionary

如果我们为每个线程分配一个单独的实例,那么实例方法肯定是线程安全的

不,如果一个实例是由一个线程访问的,那么这并不意味着它是线程安全的。这只是为了避免多线程问题

简而言之,
static
与多线程无关

instance methods are certainly thread safe, if we assign a separate instance to each thread
是当一个线程构造一个对象时,只有该线程有一个对该对象的引用,没有其他线程可以访问该对象,并且在调用实例方法时不需要线程同步

线程安全并不意味着同步

线程安全意味着,如果两个线程在某个时间尝试访问数据,数据不会损坏。线程安全还取决于您正在读取和写入的数据类型。适合单个字的数据类型(32位处理器上为int,64位处理器上为long)是线程安全的

同步—这是实现线程安全的一种方法,但对象也是不可变的

回到您的问题,例如,如果您的线程通过一个静态字段公开对对象的引用,并将其作为状态参数传递给另一个线程的方法,那么如果线程可以尝试同时进行写访问(但不是只读,这与读和写访问不同),则需要同步


因此,如果有一个对象(与方法无关)(静态或实例)可以由多个线程在读写操作中同时访问,则应使其成为线程安全的。

静态方法不是线程安全的,因为它们是静态的

他们是线程安全的,因为有人让他们线程安全。通常在.NET framework中,静态方法是线程安全的,因为有人这样编写它们

您可以同样轻松地编写非线程安全的静态成员,这里没有什么神奇之处


写线程安全的静态成员必须遵循与写线程安全的实例成员所必须遵循的规则完全相同的规则。

当您否决投票时,请解释原因,问题出在哪里。每个人都不必有同样的怀疑。停止这种沉默的向下投票,至少说出你的想法,这是相当随机和不尊重(不是向下投票)这不是一个很好的例子。不执行任何操作的方法总是线程安全的,
静态的
。注释中说modify
cd
,但是
cd
本身是一个线程安全的
ConcurrentDictionary
,这就是为什么这没问题。@weston这就是为什么我在内部修改一个类型,静态ConcurrentDictionary,而不是对一个非实例方法,我可以对一个字典进行修改,直到它对一个线程保持唯一为止,但是这对于静态方法是不可行的,所以对于这两种方法,修改静态typeinstances的类似代码可以在不同的线程上使用!这是一个错误的假设。通常,组件的设计者会阻止来自其他线程的访问,但这不是线程安全的开箱即用@Schwarzie2478主要取决于内部包含的类型,但如果在静态类型这样的类型中没有任何需要显式线程安全性的内容,那么每个线程都有一个单独的实例,就像给每个线程提供自己的内存来处理一样。我了解您的场景,但这需要用户确保在用于多线程贪婪的类型中没有此类线程安全问题,但这是Winforms生成的UI的一个非常特定的场景,通常需要BackgroundWorker使用承载/启动winform类objectNo的同一线程安全访问,控件本身负责处理UI访问内容,backgroundworker只能使用与线程无关的控件方法。。。或者,如果worker与控件在同一个线程中运行(这通常是非常错误的:-),我认为我的评论传达了一个错误的消息,我的意思是BackgroundWorker可以帮助以线程安全的方式访问控件数据更新。它是一个工作线程,当然不是在同一线程上,它将完全破坏目的。无论如何,我和winforms没有任何关系,所以我可以放心,这样的情况不会妨碍我:)但答案对你来说清楚吗,因为我感觉到您对我们的答案并不完全满意……我正在进一步测试,以便在同一线程中提出疑问。是的,实例类型避免了多线程同步场景,并且仍然执行该任务,但是静态线程很容易受到线程安全问题的影响,因为所有线程都可以访问