加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C#ThreadStatic volatile成员无法按预期工作

发布时间:2020-12-16 03:33:05 所属栏目:百科 来源:网络整理
导读:我正在阅读 tips and tricks帖子,我想我会尝试一些我之前从未做过的C#.因此,以下代码没有实际用途,但只是一个’测试函数’来查看发生了什么. 无论如何,我有两个静态私有字段: private static volatile string staticVolatileTestString = "";[ThreadStatic]
我正在阅读 tips and tricks帖子,我想我会尝试一些我之前从未做过的C#.因此,以下代码没有实际用途,但只是一个’测试函数’来查看发生了什么.

无论如何,我有两个静态私有字段:

private static volatile string staticVolatileTestString = "";
[ThreadStatic]
private static int threadInt = 0;

如您所见,我正在测试ThreadStaticAttribute和volatile关键字.

无论如何,我有一个看起来像这样的测试方法:

private static string TestThreadStatic() {
    // Firstly I'm creating 10 threads (DEFAULT_TEST_SIZE is 10) and starting them all with an anonymous method
    List<Thread> startedThreads = new List<Thread>();
    for (int i = 0; i < DEFAULT_TEST_SIZE; ++i) {
        Thread t = new Thread(delegate(object o) {
            // The anon method sets a newValue for threadInt and prints the new value to the volatile test string,then waits between 1 and 10 seconds,then prints the value for threadInt to the volatile test string again to confirm that no other thread has changed it
            int newVal = randomNumberGenerator.Next(10,100);
            staticVolatileTestString += Environment.NewLine + "tthread " + ((int) o) + " setting threadInt to " + newVal;
            threadInt = newVal;
            Thread.Sleep(randomNumberGenerator.Next(1000,10000));
            staticVolatileTestString += Environment.NewLine + "tthread " + ((int) o) + " finished: " + threadInt;
        });
        t.Start(i);
        startedThreads.Add(t);
    }

    foreach (Thread th in startedThreads) th.Join();

    return staticVolatileTestString;
}

我期望看到从这个函数返回的是这样的输出:

thread 0 setting threadInt to 88
thread 1 setting threadInt to 97
thread 2 setting threadInt to 11
thread 3 setting threadInt to 84
thread 4 setting threadInt to 67
thread 5 setting threadInt to 46
thread 6 setting threadInt to 94
thread 7 setting threadInt to 60
thread 8 setting threadInt to 11
thread 9 setting threadInt to 81
thread 5 finished: 46
thread 2 finished: 11
thread 4 finished: 67
thread 3 finished: 84
thread 9 finished: 81
thread 6 finished: 94
thread 7 finished: 60
thread 1 finished: 97
thread 8 finished: 11
thread 0 finished: 88

但是,我得到的是:

thread 0 setting threadInt to 88
thread 4 setting threadInt to 67
thread 6 setting threadInt to 94
thread 7 setting threadInt to 60
thread 8 setting threadInt to 11
thread 9 setting threadInt to 81
thread 5 finished: 46
thread 2 finished: 11
thread 4 finished: 67
thread 3 finished: 84
thread 9 finished: 81
thread 6 finished: 94
thread 7 finished: 60
thread 1 finished: 97
thread 8 finished: 11
thread 0 finished: 88

输出的第二个“一半”是预期的(我想这意味着ThreadStatic字段的工作方式与我想的一样),但似乎有一些初始输出已从第一个“半”中“跳过”.

另外,第一个“half”中的线程是乱序的,但我知道一旦调用Start(),线程就不会立即运行;但相反,内部操作系统控件将按其认为合适的方式启动线程.
编辑:不,他们不是,实际上,我只是认为他们是因为我的大脑错过了连续数字

所以,我的问题是:导致我在输出的前半部分丢失几行会出现什么问题?例如,’thread 3将threadInt设置为84’的位置在哪里?

解决方法

线程正在同时执行.从概念上讲,这是:
staticVolatileTestString += Environment.NewLine + "tthread " + ((int) o) + " setting threadInt to " + newVal;

>线程1读取staticVolatileTestString
>线程2读取staticVolatileTestString
>线程3读取staticVolatileTestString
>线程1附加内容并写回staticVolatileTestString
>线程2附加内容并写回staticVolatileTestString
>线程3附加内容并写回staticVolatileTestString

这会导致你的线路丢失.挥发无助于此;连接字符串的整个过程不是原子的.您需要围绕这些操作使用锁定:

private static object sync = new object();

lock (sync) {
    staticVolatileTestString += Environment.NewLine + "tthread " + ((int) o) + " setting threadInt to " + newVal;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读