一个写作和许多阅读线程的小数线安全

发布于 2025-02-12 00:42:06 字数 1369 浏览 1 评论 0 原文

我想了解有关某个问题的确切行为的更多信息,以便我可以决定是否使用 lock (使用绩效含义)。

Given the following pseudo code:

class Thread1
{
    public decimal TotalValue {get; private set;}
    private decimal StockAmount;
    private decimal OldPrice;
    public async Task GetStockPrices(string fictionalAsset)
    {
        while (true)
        {
            decimal totalCopy = TotalValue;
            totalCopy -= (StockAmount * OldPrice);
            OldPrice = StockPrices.GetValue(fictionalAsset);
            totalCopy += (StockAmount * OldPrice);
            TotalValue = totalCopy;
        }
    }
}

Let's assume, that Thread1 is the only Thread ever modifying TotalValue.所有其他线程(无论他们的计数如何)都只会从中读取。

可以肯定的是,读取线程访问 totalValue 时, totalValue = TotalCopy;

它的含义是什么?读取线程“ Just”会收到 totalValue (OK)的旧版本,还是可能会有另一个不需要的结果(例如0或任何其他数字 - 致命)。是否还有其他含义,例如性能。还是其他线程更新的时间? I would expect the above code to be more performant than

lock (TotalLock)
{
    TotalValue = totalCopy;
}

especially since reading threads could be many and very frequently, effectively locking up the value.

如果需要锁定,则如何提供锁? (我想像FIFO或随机) - 写线程可以分配优先级吗? (可以检查变量是否已锁定的东西,如果是的,请等待)

I would like to learn more about the exact behavior of a certain problem so That I can decide whether to use lock (with its Performance implications).

Given the following pseudo code:

class Thread1
{
    public decimal TotalValue {get; private set;}
    private decimal StockAmount;
    private decimal OldPrice;
    public async Task GetStockPrices(string fictionalAsset)
    {
        while (true)
        {
            decimal totalCopy = TotalValue;
            totalCopy -= (StockAmount * OldPrice);
            OldPrice = StockPrices.GetValue(fictionalAsset);
            totalCopy += (StockAmount * OldPrice);
            TotalValue = totalCopy;
        }
    }
}

Let's assume, that Thread1 is the only Thread ever modifying TotalValue. All other Threads (no matter their count) will only ever be reading from it.

For sure, it could happen that a reading Thread accesses TotalValue while TotalValue = totalCopy;.

What are the implications of it? Will the reading Thread "just" receive an old version of TotalValue (OK) or could there be another unwanted result (such as 0 or any other number - FATAL). Are there other implications such as performance. Or time for update on other threads?
I would expect the above code to be more performant than

lock (TotalLock)
{
    TotalValue = totalCopy;
}

especially since reading threads could be many and very frequently, effectively locking up the value.

In case Locking is required how are the locks served? (I would imagine fifo or random) - can there be a priority assigned for the writing thread? (something which checks if the variable is locked and if so, wait)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

栖竹 2025-02-19 00:42:06

您可以通过在 TotalValue 属性。 tuple-1“ rel =” nofollow noreferrer“> tuple< t> 包装器类似:

private volatile Tuple<decimal> _totalValue = new(default);

public decimal TotalValue
{
    get => _totalValue.Item1;
    private set => _totalValue = new(value);
}

volatile 关键字可确保编译器不会以不会影响单个单一的代码优化代码 - 线程程序,但可能会导致某些线程在多线程程序中失去对字段的可见性。

我的期望是,此实现应比使用锁定的速度要快一些,尤其是在 get 的情况下, set s s。否则,如果该属性的更新频率比阅读的频率更高,则垃圾收集大量短寿命 tuple&lt; 实例的成本可能会消除避免同步成本的所有好处。

You could implement the TotalValue property in a lock-free fashion, by boxing the decimals in Tuple<T> wrappers like this:

private volatile Tuple<decimal> _totalValue = new(default);

public decimal TotalValue
{
    get => _totalValue.Item1;
    private set => _totalValue = new(value);
}

The volatile keyword ensures that the compiler will not optimize the code in a way that would not affect a single-thread program, but could cause some threads to lose visibility of the field in a multithreaded program.

My expectation is that this implementation should be slightly faster than using a lock, especially if the gets greatly outnumber the sets. Otherwise, if the property is updated more frequently than it is read, the cost of garbage-collecting a large number of short-lived Tuple<decimal> instances will probably negate all the benefits of avoiding the synchronization cost.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文