线程本地存储

using System;
using System.Threading;
using System.Threading.Tasks; namespace ConsoleAppTest
{
class Program
{
static void Main(string[] args)
{
ThreadDataSlotTest.Test();
}
} /// <summary>
/// 线程本地存储
/// </summary>
class ThreadDataSlotTest
{
public static void Test()
{
for (var i = ; i < ; i++)
{
Thread.Sleep(); Task.Run(() =>
{
var slot = Thread.GetNamedDataSlot("test");
if (slot == null)
{
Thread.AllocateNamedDataSlot("test");
} if (Thread.GetData(slot) == null)
{
Thread.SetData(slot, DateTime.Now.Millisecond);
} Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":" + Thread.GetData(slot));
});
} Console.ReadLine();
}
}
}

如果使用了线程池,最好不要使用这种存储机制了,因为线程池可能不会释放使用过的线程,导致多次执行之间可能共享数据(可以每次执行前重置线程本地存储的数据)。

调用上下文

using System;
using System.Runtime.Remoting.Messaging;
using System.Threading;
using System.Threading.Tasks; namespace ConsoleAppTest
{
class Program
{
static void Main(string[] args)
{
CallContextTest.Test();
}
} /// <summary>
/// 调用上下文
/// </summary>
class CallContextTest
{
public static void Test()
{
if (CallContext.GetData("test") == null)
{
CallContext.SetData("test", "CallContext.SetData");
}
for (var i = ; i < ; i++)
{
Thread.Sleep(); Task.Run(() =>
{
if (CallContext.GetData("test") == null)
{
CallContext.SetData("test", DateTime.Now.Millisecond);
} Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":" + CallContext.GetData("test"));
});
} Console.ReadLine();
}
}
}

由上图可以知道,每次执行的数据是完全隔离的,非常符合我们的期望。但是,如果我们期望调用期间又开启了一个子线程,如何让子线程访问父线程的数据呢?这就需要使用到:“逻辑调用上下文”。

逻辑调用上下文

using System;
using System.Runtime.Remoting.Messaging;
using System.Threading;
using System.Threading.Tasks; namespace ConsoleAppTest
{
class Program
{
static void Main(string[] args)
{
ExecutionContextTest.Test();
}
} /// <summary>
/// 调用上下文
/// </summary>
class ExecutionContextTest
{
public static void Test()
{
Console.WriteLine("测试:CallContext.SetData");
Task.Run(() =>
{
CallContext.SetData("test", "wolf");
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":" + CallContext.GetData("test")); Task.Run(() =>
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":" + CallContext.GetData("test"));
});
}); Thread.Sleep(); Console.WriteLine("测试:CallContext.LogicalSetData");
Task.Run(() =>
{
CallContext.LogicalSetData("test", "wolf");
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":" + CallContext.LogicalGetData("test")); Task.Run(() =>
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":" + CallContext.LogicalGetData("test"));
}); ExecutionContext.SuppressFlow();
Task.Run(() =>
{
Console.WriteLine("SuppressFlow 之后:" + CallContext.LogicalGetData("test"));
}); ExecutionContext.RestoreFlow();
Task.Run(() =>
{
Console.WriteLine("RestoreFlow 之后:" + CallContext.LogicalGetData("test"));
});
}); Console.ReadLine();
}
}
}

注意 ExecutionContext.SuppressFlow(); 和 ExecutionContext.RestoreFlow();,它们分别能阻止传播和重置传播,默认是允许传播的。

C# 线程本地存储 调用上下文 逻辑调用上下文的更多相关文章

  1. .NET:线程本地存储、调用上下文、逻辑调用上下文

    .NET:线程本地存储.调用上下文.逻辑调用上下文 目录 背景线程本地存储调用上下文逻辑调用上下文备注 背景返回目录 在多线程环境,如果需要将实例的生命周期控制在某个操作的执行期间,该如何设计?经典的 ...

  2. 线程本地存储 ThreadLocal

    线程本地存储 · 语雀 (yuque.com) 线程本地存储提供了线程内存储变量的能力,这些变量是线程私有的. 线程本地存储一般用在跨类.跨方法的传递一些值. 线程本地存储也是解决特定场景下线程安全问 ...

  3. 线程本地存储TLS(Thread Local Storage)的原理和实现——分类和原理

    原文链接地址:http://www.cppblog.com/Tim/archive/2012/07/04/181018.html 本文为线程本地存储TLS系列之分类和原理. 一.TLS简述和分类 我们 ...

  4. 线程本地存储TLS(Thread Local Storage)的原理和实现——分类和原理

    本文为线程本地存储TLS系列之分类和原理. 一.TLS简述和分类 我们知道在一个进程中,所有线程是共享同一个地址空间的.所以,如果一个变量是全局的或者是静态的,那么所有线程访问的是同一份,如果某一个线 ...

  5. ThreadLocal(线程本地存储)

    1. ThreadLocal,即线程本地变量或线程本地存储. threadlocal的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或组件之间一些公共变量传递的 ...

  6. 线程本地存储(动态TLS和静态TLS)

    线程本地存储(TLS) 对于多线程应用程序,如果线程过于依赖全局变量和静态局部变量就会产生线程安全问题.也就是一个线程的使用全局变量可能会影响到其他也使用此全局变量的线程,有可能会造成一定的错误,这可 ...

  7. Atitit usrqbg1821 Tls 线程本地存储(ThreadLocal Storage 规范标准化草案解决方案ThreadStatic

    Atitit usrqbg1821 Tls 线程本地存储(ThreadLocal Storage 规范标准化草案解决方案ThreadStatic 1.1. ThreadLocal 设计模式1 1.2. ...

  8. 线程本地存储(Thread Local Storage, TLS)简单分析与使用

    在多线程编程中, 同一个变量, 如果要让多个线程共享访问, 那么这个变量可以使用关键字volatile进行声明; 那么如果一个变量不想使多个线程共享访问, 那么该怎么办呢? 呵呵, 这个办法就是TLS ...

  9. Java线程本地存储ThreadLocal

    前言 ThreadLocal 是一种 无同步 的线程安全实现 体现了 Thread-Specific Storage 模式:即使只有一个入口,内部也会为每个线程分配特有的存储空间,线程间 没有共享资源 ...

随机推荐

  1. C# 生成一个带数字的饼图

    using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D ...

  2. JacobMathType

    JACOB是一个 Java到微软的COM接口的桥梁.使用JACOB允许任何JVM访问COM对象,从而使JAVA应用程序能够调用COM对象,;MathType 是由美国Design Science公司开 ...

  3. ELF文件解析(一):Segment和Section

    ELF 是Executable and Linking Format的缩写,即可执行和可链接的格式,是Unix/Linux系统ABI (Application Binary Interface)规范的 ...

  4. Linux - rm 修复误删文件

    fdisk -l # 分区信息lsblk -f # 查看文件类型/etc/fstab # 查看文件格式挂载启动信息 # debugfs针对 ext2 # ext3grep针对 ext3 # extun ...

  5. Ubuntu16.04搭建QingdaoU(docker一键式部署)

    QDUOJ已经开源到2.0版本了,下面的教程不再适用,仅做纪念吧! 这几天装什么Linux.开源OJ上瘾了...竟然没去刷题...嗯,做好记录就写题啦! 先上原始网站的图: 风格不错,很符合我的口味. ...

  6. sizeof strlen区别于联系

    http://www.cnblogs.com/carekee/articles/1630789.html

  7. mysql中把一个表的数据批量导入另一个表中

    mysql中把一个表的数据批量导入另一个表中   不管是在网站开发还是在应用程序开发中,我们经常会碰到需要将MySQL或MS SQLServer某个表的数据批量导入到另一个表的情况,甚至有时还需要指定 ...

  8. 解决kali linux 开启ssh服务后连接不上的问题

    今天在手机端装了NetHunter 想连接PC的kali ,可是怎么都连不上 综合网友的经验: 1.修改sshd_config文件,命令为:vi /etc/ssh/sshd_config 将#Pass ...

  9. libSVM在matlab下的使用安装

    1) 从LIBSVM的官网http://www.csie.ntu.edu.tw/~cjlin/libsvm/上下载最新版本的LIBSVM,当前版本为libsvm-3.18.zip 2) 解压压缩包到电 ...

  10. SpringBoot使用thymeleaf模板引擎

    (1).添加pom依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactI ...