在 dotnet 程序提供了一个好用的特性,可以让字段作为线程的静态字段,也就是在相同线程的所有代码访问的静态字段是相同对象,但不同线程访问的时候是不同的



在 .NET 程序可以使用 ThreadStaticAttribute 特性标记在一个静态字段上,这样这个字段就可以做到在线程里面静态

在一个类的静态字段上面添加 ThreadStaticAttribute 可以让这个字段作为线程的静态字段,也就是在相同的线程访问的时候这个字段是静态的,拿到的对象的实例相同,但是在不同的线程拿到不相同

ThreadStaticAttribute 支持的只有静态字段,不支持静态属性,不支持普通的字段。同时添加了这个特性的静态字段不支持初始化

下面写一段代码尝试一下

    class Foo
{
public static string StaticProperty
{
get => _staticProperty;
set => _staticProperty = value;
} public static string ThreadStaticProperty
{
get => _threadStaticProperty;
set => _threadStaticProperty = value;
} [ThreadStatic] private static string _threadStaticProperty = "初始值";
private static string _staticProperty = "初始值";
}

我在一个类创建了两个不同的静态属性,一个是普通的静态属性,另一个是线程静态属性,我尝试都给两个字段初始值

        static void Main(string[] args)
{
Foo.StaticProperty = "普通静态属性";
Foo.ThreadStaticProperty = "线程静态属性"; var taskList = new List<Task>(); for (int i = 0; i < 10; i++)
{
var n = i;
var task = new Task(() =>
{
Console.WriteLine(
$"thread={Thread.CurrentThread.ManagedThreadId} 静态属性={Foo.StaticProperty} 线程静态属性={Foo.ThreadStaticProperty} 次数={n}"); Foo.StaticProperty = n.ToString();
Foo.ThreadStaticProperty = n.ToString();
}); task.Start();
taskList.Add(task);
} Task.WaitAll(taskList.ToArray());
}

我添加了上面的代码用于多个线程输出值同时修改值,在运行的时候可以看到,对于线程静态属性的输出都是空,即使我在代码添加了初始值。因为线程静态属性不支持给初始值,另外在不同的线程修改的线程静态属性是不会影响其他线程

上面代码的输出如下,可能小伙伴运行的输出和我不相同

thread=9 静态属性=普通静态属性 线程静态属性= 次数=4
thread=10 静态属性=普通静态属性 线程静态属性= 次数=3
thread=4 静态属性=普通静态属性 线程静态属性= 次数=1
thread=11 静态属性=普通静态属性 线程静态属性= 次数=7
thread=5 静态属性=普通静态属性 线程静态属性= 次数=0
thread=6 静态属性=普通静态属性 线程静态属性= 次数=2
thread=7 静态属性=普通静态属性 线程静态属性= 次数=5
thread=8 静态属性=普通静态属性 线程静态属性= 次数=6
thread=10 静态属性=3 线程静态属性=3 次数=9
thread=9 静态属性=3 线程静态属性=4 次数=8

从上面代码可以知道如果想要多个线程之间的静态字段或属性不相互影响,可以通过 ThreadStaticAttribute 如输出的最后两行,可以看到普通静态属性是在所有线程使用相同实例,于是输出的静态属性的值相同。但是线程静态属性是每个线程不相同的,在线程 10 的次数是 3 修改的属性值也就是 3 最后输出的就是 3 同时在线程 9 里面的线程静态属性和上次线程修改的相同

本文用到的类放在github 欢迎小伙伴访问

ThreadStaticAttribute

ThreadStatic静态字段在每个线程里的唯一性 - 王树伦的博客 - CSDN博客

C# [ThreadStatic] 标记静态字段对多线程执行的影响 - Ryan_zheng - 博客园

ThreadStatic特性标记静态字段对多线程执行的影响 - b0b0 - 博客园

在多线程中使用静态方法是否有线程安全问题 - 逍遥剑客的专栏 - CSDN博客

C#静态变量和静态方法的线程安全问题 - littwo - CSDN博客

我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新

如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

dotnet 线程静态字段的更多相关文章

  1. 深入理解 静态类和静态字段(C# 基础)

    序言 以前,总是被提醒,在编程过程中尽量少用静态变量,数据丢失什么的,今天有空,禁不住对静态变量的强烈好奇,跟我一起了解下静态家族的内幕吧. 静态类 定义 静态类与非静态类的重要区别在于静态类不能实例 ...

  2. (C# 基础) 静态字段,静态类,静态方法。

    静态字段被类的所有实例所共享,即此类的所有实例都访问同一内存地址. 所以该内存位置的值变更的话,这种变更对所有的实例都可见. class MyClass { ; ; public void SetVa ...

  3. C# [ThreadStatic] 标记静态字段对多线程执行的影响

    类的静态字段在类的实例中是共享的.多个线程修改实例字段的值在对其它线程来说是可见的,这也是clr默认的行为.对静态字段添加ThreadStaticAttribute标记可以改变这种默认的行为. Thr ...

  4. Python之路【番外篇】回顾&类的静态字段

    回顾 回顾:字符串.列表.字典的修改关于内存的情况 一.字符串 str1 = 'luotianshuai' str2 = str1 print id(str1) print id(str2) prin ...

  5. python的类和对象——番外篇(类的静态字段)

    什么是静态字段 在开始之前,先上图,解释一下什么是类的静态字段(我有的时候会叫它类的静态变量,总之说的都是它.后面大多数情况可能会简称为类变量.): 我们看上面的例子,这里的money就是静态字段,首 ...

  6. Spring MVC 属性文件读取注入到静态字段

    目录(?)[-] servlet-contextxml configproperties 示例属性 ConfigInfo 对应的配置bean 使用   在项目中,有些参数需要配置到属性文件xxx.pr ...

  7. C# 之 静态字段初始化

          当一个字段声明中含有 static 修饰符时,由该声明引入的字段为静态字段(静态变量).当不存在 static 修饰符时,由该声明引入的字段为实例字段(实例变量).       静态字段不 ...

  8. C#变量初始化问题:字段初始值无法引用非静态字段、方法或属性

    http://www.cnblogs.com/bluestorm/p/3432190.html 问题:字段初始值设定项无法引用非静态字段.方法或属性的问题 下面代码出错的原因,在类中定义的字段为什么不 ...

  9. java:利用静态字段和构造函数实现已建对象数查询

    问题:使用类的静态字段和构造函数,我们可以跟踪某个类所创建对象的个数. 请写一个类,在任何时候都可以向它查询"你已经创建了多少个对象?". 程序设计思想: 利用静态变量指定一个计数 ...

随机推荐

  1. Hdu 4810

    2014-05-02 15:53:50 题目连接 2013年南京现场赛的题目,现场的时候,排在我们前面的队伍基本都过了这题,我们后面的队伍也有不少过了这题,唯独我们没有.. 后来是Qingyu Sha ...

  2. 【To Read】Shortest Palindrome(KMP)

    题意:Given a string S, you are allowed to convert it to a palindrome by adding characters in front of ...

  3. C++:for范围循环特点--自我理解

    for(declaration : expression)statement for(xx-type i : P)....其一:for范围类型循环在循环前,可能会对p所在的队列里,对每一个对象进行一次 ...

  4. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第七章:在Direct3D中绘制(二)

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第七章:在Direct3D中绘制(二) 代码工程地址: https:/ ...

  5. iOS 9整理

    WWDC 2015上那些酷酷的新内容(一) http://www.cocoachina.com/apple/20150611/12120.html

  6. part12.5-定时器去抖

  7. Laravel引入第三方库的方法

    https://blog.csdn.net/will5451/article/details/52472695 1.首先在app目录下创建一个新的文件夹,命名libs(可自定义) 2.(可选)考虑到后 ...

  8. 在web.xml中配置SpringMVC

    代码如下 <servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.spr ...

  9. SuperSocket内置的命令行协议

    内置的命令行协议(接受自定义,分隔符为“:”,“,”): 命令行协议定义了每个请求必须以回车换行结尾 "\r\n". 由于 SuperSocket 中内置的命令行协议用空格来分割请 ...

  10. Python--day68--Django ORM常用字段、不常用的字段、自定义字段

    ORM和数据库的对应关系: Django ORM 常用字段和参数 常用字段 AutoField int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建 ...