线程本地存储解决了哪些问题,或者与创建独立对象实例以包含线程本地数据的标准的面向对象的习语相比,线程本地存储提供了哪些优势?
线程本地存储允许您为每个正在运行的线程提供一个类的唯一实例,这在尝试使用非线程安全类或避免由于共享状态而可能发生的同步要求时非常有用。
至于与示例相比的优势-如果生成单个线程,则与传递实例相比,使用线程本地存储几乎没有优势。
ThreadLocal<T>但是,当(直接或间接)使用ThreadPool时,类似的构造变得非常有价值。
例如,我最近有一个特定的工作过程,在该过程中,我们使用.NET中的新任务并行库进行大量的计算。可以对执行的计算的某些部分进行缓存,如果缓存中包含特定的匹配项,则在处理一个元素时可以节省大量时间。但是,缓存的信息对内存的要求很高,因此我们不希望缓存的内容超过最后一个处理步骤。
但是,尝试在线程之间共享此缓存是有问题的。为了做到这一点,我们必须同步对它的访问,并在类内部添加一些额外的检查以使它们线程安全。
而不是这样做,我重写了算法,以允许每个线程在中维护自己的私有缓存
ThreadLocal<T>。这允许线程各自维护自己的私有缓存。由于TPL使用的分区方案倾向于将元素块保持在一起,因此每个线程的本地缓存倾向于包含其所需的适当值。
这消除了同步问题,但也使我们能够将缓存保持在原位。在这种情况下,整体收益非常大。
作为一个更具体的示例,请看一下我使用TPL编写的有关聚合的博客文章。在内部,
ThreadLocal<TLocal>每当您使用ForEach重载时,Parallel类都会使用a
来保持局部状态(以及
Parallel.For<TLocal>方法)。这是将本地状态与每个线程分开的方式,以避免锁定。



