2016-07-04 43 views
0

我使用一個靜態的ThreadLocal來緩存一些重量級的對象。考慮下面的代碼:ThreadLocal和任務

class MatchItemFinder 
{ 
    private static ThreadLocal<PaddedImage> tempImage; 
    MatchItemFinder() 
    { 
     if(tempImage==null) 
      tempImage = new ThreadLocal<PaddedImage>(
      () => new PaddedImage(patchSize, patchSize)); 
    } 
    internal void DoSomething(){ 
     //Do something with tempImage.Value 
    } 
} 

當從多個任務並行庫線程中調用DoSomething()時,每個實例創建時?我的意思是顯然線程被重用,所以我的tempImage每創建一個線程或每次線程被重用時創建?

從設計的角度來看,你認爲這種緩存是一個很好的決定,還是有更好的策略來以線程安全的方式緩存大對象?

我使用.NET 4

+1

http://stackoverflow.com/questions/854976/will-values-in-my-threadstatic-variables-still-be-there-when-cycled-via-threadpo –

+0

緩存的目標是什麼?你真的想讓每個線程擁有自己的大對象副本嗎?或者你真的在尋找與所有線程共享一個*​​單個*大對象,但是以線程安全的方式?如果是後者,請查看[Lazy](https://msdn.microsoft.com/en-us/library/dd642331(v = vs.110).aspx)類。 – sstan

+0

@sstan您正在問正確的問題。我真的不想擁有250個大對象的實例。最理想的情況是具有與特定時間的併發線程數量一樣少的實例,例如對應於8個超線程核心的8個實例。懶惰不做這項工作,因爲它不是初始化。大對象是由DoSomething()操作的臨時圖像,因此單個實​​例在這裏不起作用。 –

回答

2

線程局部變量不與TPL或與線程池配合。它們是Thread -based。當任何TPL庫函數重用一個線程時,您的線程本地將被重用。

從設計的角度來看,你認爲這種緩存是一個很好的決定還是有更好的策略來以線程安全的方式緩存大型對象?

如果您的緩存項目是不可變的,則不需要線程本地項目。使用全局緩存。

+0

它們的對象不是不可變的,它們在DoSomething中操縱,所以應該存在單獨的實例 –

+0

也許你可以使用一個ObjectPool來協作檢查並返回實例嗎? – usr

+0

似乎是唯一合理的解決方案。我希望有一些不太複雜的東西可用 –