我有一个对多线程应用程序不安全的对象(以多种方式),我想提供内部检查以确保不会同时访问关键方法。
问题
我应该采用什么技术来检测和防止多个线程访问我的类?
跟踪消费者可能使用的所有方法、属性等的 Thread.ID 是否足够?
我有一个对多线程应用程序不安全的对象(以多种方式),我想提供内部检查以确保不会同时访问关键方法。
问题
我应该采用什么技术来检测和防止多个线程访问我的类?
跟踪消费者可能使用的所有方法、属性等的 Thread.ID 是否足够?
只需记录它不是线程安全的。这是 .NET 中的类使用的约定。
会有帮助吗?
lock(_padLock)
{
....
}
或者,如果您从外部访问对象,则可以使用 Mutex 对象。
您可以使用的最佳内部检查是lock
其他人建议的设置。但是这里有一些值得研究的创造性方法,看看它们是否能解决您的特定问题。我遇到的问题是,我不知道是否只有类的一部分是不安全的,是否让不同的线程使用类的不同实例是否是线程安全的。所以这里有一些lock
可以缓解某些情况的组合
场景 1:静态类/方法 - 这将确保无论谁访问静态类/成员,如果另一个线程已经这样做,他们将被阻止。
public static class UnsafeStaticClass
{
private static object _padLock = new object();
public static void UnsafeStaticMethod()
{
lock(_padLock)
{
// Do Work
}
}
}
场景二:普通类,实例可以并行,但每个实例只允许调用一次。多个实例可以同时运行代码块。
public class UnsafeClass
{
private object _padLock = new object();
public void UnsafeMethod()
{
lock(_padLock)
{
// Do Work
}
}
}
场景 3:一个 Class 实例,它与不安全的静态方法交互 - 因此需要确保只存在对 ouside 静态方法的单个调用。无论有多少实例,一次只有一个可以运行该方法,因为它锁定在一个静态对象上。
public void UnsafeClass
{
private static object _padLock = new object();
public void UnsafeInstanceMethod()
{
lock(_padlock)
{
// Do Work
}
}
}
属性MethodImplOptions有一个用于 Synchronized 的枚举
指定该方法一次只能由一个线程执行。静态方法锁定类型,而实例方法锁定实例。只有一个线程可以在任何实例函数中执行,并且只有一个线程可以在任何类的静态函数中执行。
...虽然不推荐这样做。此方法的功能等同于lock(this)
允许其他类意外或恶意获取锁
另一种选择是使用单独的对象用于锁定。这样做时,它可以被标记为只读,除非它是像 Spinlock 这样的结构。简而言之:不要对 Spinlock 使用 readonly 属性:这会导致每次调用 SpinLock 或 _lock.Enter 获取对象的新副本并成功。如果这样做,腐败很可能发生。
class myClass
{
private object myLock; //OK
private readonly object myLock2; //OK
private readonly SpinLock myLock3; //WARNING: Value type, won't work as intended
private SpinLock myLock4; //OK
void DoStuff()
{
lock(myLock4)
{
// some quick instructions... say 10 or fewer
}
}
}
检查线程 ID 将捕获多线程使用,因为如果有人在多线程程序中使用它,它会抛出消息,希望阻止人们使用该程序。它不会优雅,但它最终会提醒人们注意麻烦。该程序的使用方式将决定在人们意识到错误之前造成严重伤害的可能性。
但总的来说,单线程代码在多线程程序中运行得非常好。它快速且(相对)容易编写。(当然,调用代码必须非常小心。)您将放弃您的类的这种能力,并将其限制为仅在会从头到尾在一个线程中运行它的程序中运行的程序。例如,在 Windows 桌面程序中,这几乎意味着它必须在事件队列中运行,这意味着它在运行时必然会占用事件队列——没有工作线程!
大多数集合类都是单线程的,但在多线程程序中得到广泛使用。我会将它们用作单线程编码的模型。