面向云技术架构 - 痴者工良

  • 首页
  • 工良写的电子书
    • kubernetes 教程
    • 从 C# 入门 Kafka
    • 多线程和异步
    • 动态编程-反射、特性、AOP
    • 表达式树
  • 本站文章导航
  • 隐私政策
愿有人陪你颠沛流离
遇到能让你付出的事物或者人,都是一种运气。
能遇到,就该珍惜。或许你们最终没能在一起,但你会切实地感受到力量。
正因为这样,那段相遇才变得有价值,才没有辜负这世间的每一段相遇。
  1. 首页
  2. .NET
  3. 正文

C# ThreadLocal 的使用误区

2022年8月4日 746点热度 1人点赞 0条评论
内容纲要

如下面代码:

[ThreadStatic]
private bool HasCreated = false;
[ThreadStatic]
private int Value = 0;

void Main()
{
    ThreadLocal<string> a = new ThreadLocal<string>(() =>
    {
        if (HasCreated) return Value.ToString();
        else
        {
            Value = Thread.CurrentThread.ManagedThreadId;
            HasCreated = true;
            return Value.ToString();
        }
    });

    new Thread(() =>
    {
        Console.WriteLine("代码1 值:" + a.Value);
    }).Start();

    new Thread(() =>
    {
        Console.WriteLine("代码2 值:" + a.Value);
    }).Start();
}

设想上,两个线程输出的数字应该是不一样的,但是无论怎么运行,两个线程输出的数字都是一样的。
开始以为是两个线程间隔时间太短,造成两个代码的线程复用了。

然后改代码,将两个线程同时运行。

![file](https://www.whuanle.cn/wp-content/uploads/2022/08/image-1659579697218.png)[ThreadStatic]
private bool HasCreated = false;
[ThreadStatic]
private int Value = 0;

void Main()
{
    ThreadLocal<string> a = new ThreadLocal<string>(() =>
    {
        if (HasCreated) return Value.ToString();
        else
        {
            Value = Thread.CurrentThread.ManagedThreadId;
            HasCreated = true;
            return Value.ToString();
        }
    });

    new Thread(() =>
    {
        Thread.Sleep(1000);
        Console.WriteLine("代码1 值:" + a.Value);
    }).Start();

    new Thread(() =>
    {
        Console.WriteLine("代码2 值:" + a.Value);
        Thread.Sleep(1000);
    }).Start();
}

但是,输出还是一模一样。
看了一下 ThreadLocal 的源码,其 Func<T> 是延迟执行的,只有使用 .Value 的时候才会执行。

file

为了更好判断问题,再次改代码:

[ThreadStatic]
private bool HasCreated = false;
[ThreadStatic]
private int Value = 0;

void Main()
{
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    ThreadLocal<string> a = new ThreadLocal<string>(() =>
    {
        if (HasCreated) return Value.ToString();
        else
        {
            Value = Thread.CurrentThread.ManagedThreadId;
            HasCreated = true;
            return Value.ToString();
        }
    });

    new Thread(() =>
    {
        Console.WriteLine("代码1 线程id:" + Thread.CurrentThread.ManagedThreadId);
        Console.WriteLine("代码1 值:" + a.Value);
        Thread.Sleep(1000);
    }).Start();

    new Thread(() =>
    {
        Thread.Sleep(1000);
        Console.WriteLine("代码2 线程id:" + Thread.CurrentThread.ManagedThreadId);
        Console.WriteLine("代码2 值:" + a.Value);

    }).Start();

    Thread.Sleep(2000);
}

file

可以看到,Value 不是 Main 的线程 id,是代码1 的 id。
一旦有一个线程设置了 Value,后面的线程都会跟着使用这个 HasCreate、Value。
但是里面的代码 .Value 每次都会执行 Func<T> ,但是为什么取到的 HasCreate 是相同的值?

emmm....

原来是忘记了加上 static。。。
[ThreadStatic] 修饰的变量,只能是静态字段。

[ThreadStatic]
private static bool HasCreated = false;
[ThreadStatic]
private static int Value = 0;

file

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: c threadlocal 使用 误区
最后更新:2022年8月4日

痴者工良

高级程序员劝退师

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

COPYRIGHT © 2022 whuanle.cn. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

粤ICP备18051778号

粤公网安备 44030902003257号