相关疑难解决方法(0)

模拟在C#中撕掉一个双

我正在使用32位计算机运行,并且我能够使用以下快速命中的代码片段来确认长值可以撕裂.

        static void TestTearingLong()
        {
            System.Threading.Thread A = new System.Threading.Thread(ThreadA);
            A.Start();

            System.Threading.Thread B = new System.Threading.Thread(ThreadB);
            B.Start();
        }

        static ulong s_x;

        static void ThreadA()
        {
            int i = 0;
            while (true)
            {
                s_x = (i & 1) == 0 ? 0x0L : 0xaaaabbbbccccddddL;
                i++;
            }
        }

        static void ThreadB()
        {
            while (true)
            {
                ulong x = s_x;
                Debug.Assert(x == 0x0L || x == 0xaaaabbbbccccddddL);
            }
        }
Run Code Online (Sandbox Code Playgroud)

但是当我尝试与双打类似的东西时,我无法得到任何撕裂.有谁知道为什么?据我从规范中可以看出,只有浮点数的赋值才是原子的.分配给双人应该有撕裂的风险.

    static double s_x;

    static void TestTearingDouble()
    {
        System.Threading.Thread A = new System.Threading.Thread(ThreadA);
        A.Start(); …
Run Code Online (Sandbox Code Playgroud)

.net c# multithreading double-precision atomicity

18
推荐指数
2
解决办法
789
查看次数

阅读双重不是线程安全的吗?

更新:我在Eric Lippert另一个问题的回答中偶然发现了这个问题(他引用了这个规范):

其他类型的读写,包括long,ulong,double和decimal,以及用户定义的类型,不保证是原子的.

好了,阅读double不是原子.这意味着可以在读取中间修改该值,对吧?那么如何以double原子方式读取值?


我注意到有一种价值Interlocked.Read方法long.这对我来说很有意义,因为读取64位值必须需要两个步骤,因此就像其他所有非原子动作一样受到竞争条件的影响.

但目前还没有Interlocked.Readdouble价值观,即使System.Double是一个64位的值.

我在我的程序中看到一些奇怪的行为,我的GUI double在文本框中显示,而double其他线程也经常更新,在大多数时间显示正确的值(在200.0附近),然后偶尔随机显示错误值(如-0.08).

也许这是一个线程问题,或者也许是其他问题.但首先我想缩小可能性.那么:正在阅读double线程安全吗?

.net double thread-safety

15
推荐指数
3
解决办法
3551
查看次数

parallel.foreach有效,但为什么呢?

谁能解释一下,为什么这个程序返回sqrt_min的正确值?

int n = 1000000;

double[] myArr = new double[n];
for(int i = n-1 ; i>= 0; i--){ myArr[i] = (double)i;}

// sqrt_min contains minimal sqrt-value
double sqrt_min = double.MaxValue;

Parallel.ForEach(myArr, num =>
{
double sqrt = Math.Sqrt(num); // some time consuming calculation that should be parallized
if(sqrt < sqrt_min){ sqrt_min = sqrt;}
});
Console.WriteLine("minimum: "+sqrt_min);
Run Code Online (Sandbox Code Playgroud)

.net c# thread-safety race-condition parallel.foreach

7
推荐指数
2
解决办法
1706
查看次数

c#struct array的并发性

给定一个struct数组:

public struct Instrument
{
    public double NoS;
    public double Last;
}

var a1 = new Instrument[100];
Run Code Online (Sandbox Code Playgroud)

并且一个线程任务池正在写入这些元素,因为单个元素最多可以同时由两个线程写入,每个双字段一个(有效地通过主题进行上游排队).

并且知道双重可以在64位上原子地写入.(编辑这个错误地说原来是32位)

我需要使用数组中的所有值定期执行计算,并且我希望它们在计算期间保持一致.

所以我可以使用以下方法对数组进

var snapshot = a1.Clone();
Run Code Online (Sandbox Code Playgroud)

现在我的问题是关于同步的具体细节.如果我使成员易变,我认为这根本不会帮助克隆,因为读/写aquire/releases不在数组级别.

现在我可以有一个数组锁,但这会在最常见的数据写入数组的过程中引起很多争论.所以不太理想.

或者我可以有一个每行锁定,但这将是一个真正的痛苦,因为他们都需要在克隆之前被获取,同时我有所有备份的写入.

现在,如果快照没有最新值(如果它只是微秒等)并不重要,所以我想我可能会因为没有锁而逃脱.我唯一担心的是,是否存在持续时间段内没有缓存写回的情况.这是我应该担心的吗?编写器在TPL数据流中,唯一的逻辑是在结构中设置两个字段.我真的不知道函数范围是如何或者是否与缓存回写相关联.

思考/建议吗?

编辑:如果我使用互锁写入结构中的变量怎么样?

edit2:写入量比读取量高很多.写入Nos&Last字段还有两个单独和并发的服务.所以他们可以同时写入.这导致参考对象方法存在原子性问题.

edit3:更多细节.假设数组是30-1000个元素,每个元素可以每秒多次更新.

c# concurrency struct volatile memory-barriers

2
推荐指数
1
解决办法
948
查看次数