AsnycLocal与ThreadLocal
程序员文章站
2022-04-08 21:30:38
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会获取到之前的上下文,此时会出现意料之外的问题,从现象上看报错可能会是一个概率性问题。