gpt4 book ai didi

c# - 这是在 C# 中创建线程安全类的好设计吗?

转载 作者:可可西里 更新时间:2023-11-01 08:20:15 25 4
gpt4 key购买 nike

通常,当我想要一个线程安全的类时,我会执行如下操作:

public class ThreadSafeClass
{
private readonly object theLock = new object();

private double propertyA;
public double PropertyA
{
get
{
lock (theLock)
{
return propertyA;
}
}
set
{
lock (theLock)
{
propertyA = value;
}
}
}

private double propertyB;
public double PropertyB
{
get
{
lock (theLock)
{
return propertyB;
}
}
set
{
lock (theLock)
{
propertyB = value;
}
}
}

public void SomeMethod()
{
lock (theLock)
{
PropertyA = 2.0 * PropertyB;
}
}
}

它有效,但非常冗长。有时我什至为每个方法和属性创建一个锁对象,这会导致更加冗长和复杂。

我知道也可以使用 Synchronization 属性锁定类,但我不确定它的扩展性如何——因为我经常期望拥有数十万甚至数百万个线程安全对象实例.这种方法将为该类的每个实例创建一个同步上下文,并要求该类派生自 ContextBoundObject,因此不能派生自任何其他对象——因为 C# 不允许多重继承——这是一个阻碍在许多情况下。

编辑:正如一些响应者所强调的,没有“银弹”线程安全类设计。我只是想了解我使用的模式是否是好的解决方案之一。当然,在任何特定情况下的最佳解决方案都取决于问题。下面的几个答案包含应考虑的替代设计。

编辑:此外,线程安全的定义不止一种。例如,在我上面的实现中,以下代码不是线程安全的:

var myObject = new ThreadSafeClass();
myObject.PropertyA++; // NOT thread-safe

那么,上面的类定义是否代表了一种好的方法?如果不是,对于具有类似行为且对于类似用途集线程安全的设计,您会推荐什么?

最佳答案

多线程问题没有“一刀切”的解决方案。对创建不可变类进行一些研究并了解不同的同步原语。

这是一个半不可变the-programmers-immutable 类的示例。

public class ThreadSafeClass
{
public double A { get; private set; }
public double B { get; private set; }
public double C { get; private set; }

public ThreadSafeClass(double a, double b, double c)
{
A = a;
B = b;
C = c;
}

public ThreadSafeClass RecalculateA()
{
return new ThreadSafeClass(2.0 * B, B, C);
}
}

此示例将您的同步代码移动到另一个类中并序列化对实例的访问。实际上,您真的不希望在任何给定时间有多个线程对一个对象进行操作。

public class ThreadSafeClass
{
public double PropertyA { get; set; }
public double PropertyB { get; set; }
public double PropertyC { get; set; }

private ThreadSafeClass()
{

}

public void ModifyClass()
{
// do stuff
}

public class Synchronizer
{
private ThreadSafeClass instance = new ThreadSafeClass();
private readonly object locker = new object();

public void Execute(Action<ThreadSafeClass> action)
{
lock (locker)
{
action(instance);
}
}

public T Execute<T>(Func<ThreadSafeClass, T> func)
{
lock (locker)
{
return func(instance);
}
}
}
}

这是一个简单的示例,说明您将如何使用它。它可能看起来有点笨拙,但它允许您一次对实例执行许多操作。

var syn = new ThreadSafeClass.Synchronizer();

syn.Execute(inst => {
inst.PropertyA = 2.0;
inst.PropertyB = 2.0;
inst.PropertyC = 2.0;
});

var a = syn.Execute<double>(inst => {
return inst.PropertyA + inst.PropertyB;
});

关于c# - 这是在 C# 中创建线程安全类的好设计吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2135222/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com