欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

AsnycLocal与ThreadLocal

程序员文章站 2022-07-28 11:35:18
AsnycLocal与ThreadLocal AsnyncLocal与ThreadLocal都是存储线程上下文的变量,但是,在实际使用过程中两者又有区别主要的表现在: AsyncLocal变量可以在父子线程中传递,创建子线程时父线程会将自己的AsyncLocal类型的上下文变量赋值到子线程中,但是, ......

asnyclocal与threadlocal

asnynclocal与threadlocal都是存储线程上下文的变量,但是,在实际使用过程中两者又有区别主要的表现在:

  • asynclocal变量可以在父子线程中传递,创建子线程时父线程会将自己的asynclocal类型的上下文变量赋值到子线程中,但是,当子线程改变线程上下文中asnyclocal变量值后,父线程不会同步改变。也就是说asnyclocal变量只会影响他的子线程,不会影响他的父级线程。
  • treadlocal只是当前线程的上下文变量,不能在父子线程间同步。
using system;
using system.threading;
using system.threading.tasks;

namespace await_aysnc
{
    class program
    {
        static threadlocal<int> threadobj = new threadlocal<int>();
        static asynclocal<int> asyncobj = new asynclocal<int>();

        static void main(string[] args)
        {
            asyncobj.value = 1;
            threadobj.value = 1;
            console.writeline($"task执行前:asyncobj= {asyncobj.value} threadobj= {threadobj.value} threeadid = {thread.currentthread.managedthreadid}");
            task.run(async() =>
            {
                console.writeline($"runasync异步执行前:asyncobj= {asyncobj.value} threadobj= {threadobj.value} threeadid = {thread.currentthread.managedthreadid}");
                await runasync();
                console.writeline($"runasync异步执行后:asyncobj = {asyncobj.value} threadobj= {threadobj.value} threeadid = {thread.currentthread.managedthreadid}");
            });
            console.writeline($"task执行后:asyncobj= {asyncobj.value} threadobj= {threadobj.value} threeadid = {thread.currentthread.managedthreadid}");
            console.read();
        }

        static async task runasync()
        {           
            console.writeline($"delay异步执行前:asyncobj = {asyncobj.value} threadobj= {threadobj.value} threeadid = {thread.currentthread.managedthreadid} ");
            asyncobj.value = 2;
            threadobj.value = 2;
            await task.delay(100);
            console.writeline($"delay异步执行后:asyncobj = {asyncobj.value} threadobj= {threadobj.value} threeadid = {thread.currentthread.managedthreadid}");
        }
    }

}
task执行前:asyncobj= 1 threadobj= 1 threeadid = 1
task执行后:asyncobj= 1 threadobj= 1 threeadid = 1
runasync异步执行前:asyncobj= 1 threadobj= 0 threeadid = 3
delay异步执行前:asyncobj = 1 threadobj= 0 threeadid = 3
delay异步执行后:asyncobj = 2 threadobj= 0 threeadid = 4
runasync异步执行后:asyncobj = 1 threadobj= 0 threeadid = 4

从结果上可以看出一下结论:

  • runasync执行前threadlocal值被切成0即threadlocal变量在新线程里面没有继承主线程的上下文变量,但是asynclocal继承了。
  • delay返回后,线程id变了,同时,theadlocal中的变量为0。
  • runasync结束后aynclocal又切回主线程的上下文值,,同样threadlocal中的值丢失。
  • 由于await执行完返回之后,.net会在线程池中随机选取一个线程来执行await之后的逻辑,所以,await之后同时也会有一定几率获取到之前的线程,如果出现这种情形,treadlocal会获取到之前的上下文,此时会出现意料之外的问题,从现象上看报错可能会是一个概率性问题。