多线程之旅(10)_QueueUserWorkItem和UnsafeQueueUserWorkItem的区别「建议收藏」

多线程之旅(10)_QueueUserWorkItem和UnsafeQueueUserWorkItem的区别「建议收藏」这是个比较冷门的点,是我在写多线程之旅(2)_创建一个属于自己的精简线程池_线程调度策略——附C#源码这篇文章时,发现在做线程队列时,官方选用的是UnsafeQueueUserWorkItem,而不是常见的QueueUserWorkItem,所以后续我就对这两个方法调查一番,发现资料也不多,总结一下。一、官方定义首先看一下官方的定义:来源:https://docs.microsof…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

这是个比较冷门的点,是我在写多线程之旅(2)_创建一个属于自己的精简线程池_线程调度策略——附C#源码这篇文章时,发现在做线程队列时,官方选用的是UnsafeQueueUserWorkItem,而不是常见的QueueUserWorkItem,所以后续我就对这两个方法调查一番,发现资料也不多,总结一下。

一、官方定义

首先看一下官方的定义:

来源:

https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.threadpool.queueuserworkitem?view=netframework-4.8

https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.threadpool.unsafequeueuserworkitem?view=netframework-4.8

(1)QueueUserWorkItem(WaitCallback, Object)

将方法排入队列以便执行,并指定包含该方法所用数据的对象。 此方法在有线程池线程变得可用时执行。

参数:

WaitCallback,它表示要执行的方法。

Object,包含方法所用数据的对象。

(2)UnsafeQueueUserWorkItem(WaitCallback, Object)

将指定的委托排队到线程池,但不会将调用堆栈传播到辅助线程。

参数:

 WaitCallback,表示当线程池中的线程选择工作项时调用的委托。

Object,在接受线程池服务时传递给委托的对象。

二、解析

看着上面的官方解释,一如既往的迷,不用担心是之上问题,或许是因为翻译问题使得很难理解。

下面我用一篇文章(http://www.csframework.com/archive/2/arc-2-20110727-1759.htm)中的一段描述来解释这个问题:

threadpool类有一个UnsafeQueueUserWorkItem方法。该方法与平时调用的QueueUserWorkItem方法非常相似。下面先简单介 绍一下这两个方法的区别:

当有线程试图访问一个受限资源(如打开一个文件)时,clr将执行一个代码访问安全(code access security, cas)检查。也就是说,clr将检查调用线程的调用堆栈中的所有程序集是否都有访问资源的许可权限。如果有一些程序集没有所需 的许可权限,clr将抛出一个securityexception异常。假设正在执行代码的线程所在的程序集没有打开文件的许可权限,那么在线程试图打开文件时,clr将抛出一个securityexception异常。

为让线程继续运行,线程可以在线程池的队列加入一个工作项,让线程池中的线程来执行打开文件的代码。当然这必须在拥 有合适许可权限的程序集中进行。这种“工作区”智取安全权限的现象可以允许怀恶意的代码对受限资源进行严重破坏。为阻止这 种获得安全权限的方式,QueueUserWorkItem方法内部遍历调用线程的堆栈,并捕获所有被授予的安全权限。然后,当线程池中的线程开始执行时,这些权限再与线程结合。因此,线程池中的线程以调用QueueUserWorkItem方法的线程相同的权限集来完成运行。

(看着是有些绕,简单说呢,QueueUserWorkItem作为一种安全的线程池机制,其内部有一个功能,就是能遍历调用线程池中线程的‘堆栈’,获取堆栈中程序集所具有的安全权限。当堆栈对该线程调用时,这个线程的就继承了调用他的堆栈内容所具有的权限。这样就避免了权限较小的堆栈通过调用权限较大的线程,来获取非法数据。

就好比堆栈里的内容没有打开文件的权限,但是线程池中的线程可以打开文件,那么堆栈通过调用线程池里的线程来打开文件,从而获取打开文件的权限。)

OK,我们再来了解一下UnsafeQueueUserWorkItem

遍历线程的堆栈并捕获所有的安全权限与性能紧密相关。如果希望改进受计算限制的异步操作的排队性能,可以调用 UnsafeQueueUserWorkItem方法。该方法只将工作项加入到线程池的队列中,而不遍历调用线程的堆栈。最后结果是这个方法比 QueueUserWorkItem方法执行得快,但它在应用程序中打开了一个潜在的安全漏洞。仅当可以确认线程池中的线程执行的代码不触及受限资源时,或确信接触这部分资源不会出现问题时,我们才可以调用unsafequeueuserwork-item方法。同样,还需注意调用该方 法需要使securitypermission的controlpolicy标记和controlevidence标记开启,可阻止未信任的代码偶然或故意提升它的许可权 限。

(有了上面的铺垫,UnsafeQueueUserWorkItem就很好理解了,为了追求效率,UnsafeQueueUserWorkItem对堆栈里的内容信任,不再去遍历堆栈信息,读取权限,而是直接执行。)

三、其他

还有一篇文章(https://www.cnblogs.com/JeffreyZhao/archive/2009/07/22/thread-pool-1-the-goal-and-the-clr-thread-pool.html)中的一段话,提到了两者的关联,贴上来

我们在编写程序的时候,可以使用ThreadPool类的两个静态方法:QueueUserWorkItem和UnsafeUserQueueWorkItem向CLR线程池中添加任务(一个WorkCallback委托对象),这两个方法的区别,在于前者会收集调用方的ExecutionContext,也就是保留了的当前线程的执行信息(如认证或语言文化等),使任务最终会在“创建”时刻的环境中执行2——后者就不会。因此,如果比较两个方法的绝对性能,Unsafe方法会略胜一筹。但是平时还是建议使用QueueUserWorkItem方法,因为保留执行上下文会避免很多麻烦事情,且这点性能损耗其实算不上什么。

这段话表述不是很清楚,但大概意思也表明了QueueUserWorkItem方法在处理线程时会做更多的信息评判,更加安全。而相比之下UnsafeQueueUserWorkItem的执行效率更高。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/190043.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 前端必备技能之如何制作精灵图「建议收藏」

    前端必备技能之如何制作精灵图「建议收藏」为什么要用精灵图?比如京东首页的这些icon,如果每个icon都去请求一个资源。是非常浪费资源的。因为我们浏览器在同一个域名下并发加载的资源(CSS、JS、图片等)数量是有限的。我们可以将这些icon放到一张图片,通过截取这张图片的不同的区域,拿到不同的icon制作一个背景透明的Icon截图你喜欢的logo,最好是正方形。打开ps,使用快速选择工具选择白色区域ctrl+x删除…

    2022年6月3日
    129
  • 透彻掌握Spring整合MyBatis的原理彻底征服面试官,建议收藏

    透彻掌握Spring整合MyBatis的原理彻底征服面试官,建议收藏  在MyBatis篇内容的最后我们来给大家详细介绍下Spring是如何整合MyBatis的。让大家彻底掌握MyBatis的底层设计原理及实现。MyBatis整合Spring原理  把MyBatis集成到Spring里面,是为了进一步简化MyBatis的使用,所以只是对MyBatis做了一些封装,并没有替换MyBatis的核心对象。也就是说:MyBatisjar包中的SqlSessionFactory、SqlSession、MapperProxy这些类都会用到。mybatis-spring.jar里

    2022年5月30日
    38
  • 整数除以整数的小数除法计算题_原码一位除法

    整数除以整数的小数除法计算题_原码一位除法题目描述a/b。a,b为integer范围内的整数。求a/b的前n位小数商。输入abn输出一行数字样例输入976150样例输出1.59016393442622950819672131147540983606557377049180满分代码:vara,b,n,i:longint;beginreadln(a,b,n);write(adivb,’…

    2025年7月15日
    4
  • 简单说明什么是宏观社会环境和微观社会环境?_kafka是什么

    简单说明什么是宏观社会环境和微观社会环境?_kafka是什么Kafka通俗理解Apachekafka是消息中间件的一种,我发现很多人不知道消息中间件是什么,在开始学习之前,我这边就先简单的解释一下什么是消息中间件,只是粗略的讲解,目前kafka已经可以做更多的事情。举个例子,生产者消费者,生产者生产鸡蛋,消费者消费鸡蛋,生产者生产一个鸡蛋,消费者就消费一个鸡蛋,假设消费者消费鸡蛋的时候噎住了(系统宕机了),生产者还在生产鸡蛋,那新生产的鸡蛋就丢失了。…

    2022年10月7日
    2
  • native 15 激活码【在线注册码/序列号/破解码】

    native 15 激活码【在线注册码/序列号/破解码】,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月19日
    48
  • sql server 清空表数据「建议收藏」

    sql server 清空表数据「建议收藏」truncatetable BirthdayReminderDetail   truncate表+表名

    2022年5月30日
    44

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号