日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多线程中Local Store Slot(本地存储槽)[转]

發布時間:2025/3/15 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程中Local Store Slot(本地存储槽)[转] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 使用ThreadStatic特性

ThreadStatic特性是最簡單的TLS使用,且只支持靜態字段,只需要在字段上標記這個特性就可以了:

  • [ThreadStatic]??
  • static string str = "hehe";??
  • static void Main()??
  • {??
  • //另一個線程只會修改自己TLS中的str變量
  • ??? Thread th = new Thread(() => { str = "Mgen"; Display(); });??
  • ??? th.Start();??
  • ??? th.Join();??
  • ??? Display();??
  • }??
  • static void Display()??
  • {??
  • ??? Console.WriteLine("{0} {1}", Thread.CurrentThread.ManagedThreadId, str);??
  • }?
  • 運行結果:

    1 hehe
    3 Mgen

    可以看到,str靜態字段在兩個線程中都是獨立存儲的,互相不會被修改。

    2. 使用命名的LocalDataStoreSlot類型

    顯然ThreadStatic特性只支持靜態字段太受限制了。.NET線程類型中的LocalDataStoreSlot提供更好的TLS支持。我們先來看看命名的LocalDataStoreSlot類型,可以通過Thread.AllocateNamedDataSlot來分配一個命名的空間,通過Thread.FreeNamedDataSlot來銷毀一個命名的空間。空間數據的獲取和設置則通過Thread類型的GetData方法和SetData方法。

  • static void Main()??
  • {??
  • //創建Slot
  • ??? LocalDataStoreSlot slot = Thread.AllocateNamedDataSlot("slot");??
  • //設置TLS中的值
  • ??? Thread.SetData(slot, "hehe");??
  • //修改TLS的線程
  • ??? Thread th = new Thread(() =>??
  • ??????? {??
  • ??????????? Thread.SetData(slot, "Mgen");??
  • ??????????? Display();??
  • ??????? });??
  • ??? th.Start();??
  • ??? th.Join();??
  • ??? Display();??
  • //清除Slot
  • ??? Thread.FreeNamedDataSlot("slot");??
  • }??
  • //顯示TLS中Slot值
  • static void Display()??
  • {??
  • ??? LocalDataStoreSlot dataslot = Thread.GetNamedDataSlot("slot");??
  • ??? Console.WriteLine("{0} {1}", Thread.CurrentThread.ManagedThreadId, Thread.GetData(dataslot));??
  • }?
  • 輸出:

    3 Mgen
    1 hehe

    3. 使用未命名的LocalDataStoreSlot類型

    線程同樣支持未命名的LocalDataStoreSlot,未命名的LocalDataStoreSlot不需要手動清除,分配則需要Thread.AllocateDataSlot方法。注意由于未命名的LocalDataStoreSlot沒有名稱,因此無法使用Thread.GetNamedDataSlot方法,只能在多個線程中引用同一個LocalDataStoreSlot才可以對TLS空間進行操作,將上面的命名的LocalDataStoreSlot代碼改成未命名的LocalDataStoreSlot執行:

  • //靜態LocalDataStoreSlot變量
  • static LocalDataStoreSlot slot;??
  • static void Main()??
  • {??
  • //創建Slot
  • ??? slot = Thread.AllocateDataSlot();??
  • //設置TLS中的值
  • ??? Thread.SetData(slot, "hehe");??
  • //修改TLS的線程
  • ??? Thread th = new Thread(() =>??
  • ??????? {??
  • ??????????? Thread.SetData(slot, "Mgen");??
  • ??????????? Display();??
  • ??????? });??
  • ??? th.Start();??
  • ??? th.Join();??
  • ??? Display();??
  • }??
  • //顯示TLS中Slot值
  • static void Display()??
  • {??
  • ??? Console.WriteLine("{0} {1}", Thread.CurrentThread.ManagedThreadId, Thread.GetData(slot));??
  • }??
  • 4. 使用.NET 4.0的ThreadLocal<T>類型

    .NET 4.0在線程方面加入了很多東西,其中就包括ThreadLocal<T>類型,他的出現更大的簡化了TLS的操作。ThreadLocal<T>類型和Lazy<T>驚人相似,構造函數參數是Func<T>用來創建對象(當然也可以理解成對象的默認值),然后用Value屬性來得到或者設置這個對象。ThreadLocal的操作或多或少有點像上面的未命名的LocalDataStoreSlot,但ThreadLocal感覺更簡潔更好理解。

  • static ThreadLocal<string> local;??
  • static void Main()??
  • {??
  • //創建ThreadLocal并提供默認值
  • ??? local = new ThreadLocal<string>(() => "hehe");??
  • //修改TLS的線程
  • ??? Thread th = new Thread(() =>??
  • ??????? {??
  • ??????????? local.Value = "Mgen";??
  • ??????????? Display();??
  • ??????? });??
  • ??? th.Start();??
  • ??? th.Join();??
  • ??? Display();??
  • }??
  • //顯示TLS中數據值
  • static void Display()??
  • {??
  • ??? Console.WriteLine("{0} {1}", Thread.CurrentThread.ManagedThreadId, local.Value);??
  • }?
  • 輸出:

    3 Mgen

    1 hehe?

    5. 強調一下不同方法和TLS的默認值
    上面代碼都是一個一個線程設置值,另一個線程直接修改值然后輸出,不會覺察到TLS中默認值的狀況,下面專門強調一下不同方法的默認值狀況。ThreadStatic不提供默認值:

  • [ThreadStatic]??
  • static int i = 123;??
  • static void Main()??
  • {??
  • //輸出本地線程TLS數據值
  • ??? Console.WriteLine(i);??
  • //輸出另一個線程TLS數據值
  • ??? ThreadPool.QueueUserWorkItem(_ => Console.WriteLine(i));??
  • //控制臺等待線程結束
  • ??? Console.ReadKey();??
  • }?
  • 輸出:
    123

    0

    顯然本地線程TLS數據時123,而靜態變量的默認值不會在另一個線程中初始化的。

    LocalDataStoreSlot很容易可以看出來,不可能有默認值,因為初始化只能構造一個空間,而不能賦予它值,Thread.SetData顯然只會在TLS中設置數據,還是用代碼演示一下:

  • static LocalDataStoreSlot slot = Thread.AllocateDataSlot();??
  • static void Main()??
  • {??
  • ??? Thread.SetData(slot, 123);??
  • //輸出本地線程TLS數據值
  • ??? Console.WriteLine(Thread.GetData(slot));??
  • //輸出另一個線程TLS數據值
  • ??? ThreadPool.QueueUserWorkItem(_ => Console.WriteLine(Thread.GetData(slot) == null));??
  • //控制臺等待線程結束
  • ??? Console.ReadKey();??
  • }?
  • 輸出:
    123
    True
    第二行是True,那么另一個線程中的數據是null。

    最后重點:.NET 4.0后的ThreadLocal會提供默認值的,還記得我上面說的那句話“ThreadLocal的操作或多或少有點像上面的未命名的LocalDataStoreSlot”?有人可能會問那為什么要創造出ThreadLocal?還有一個很大的區別ThreadLocal可以提供TLS中數據的默認值。(另外還有ThreadLocal是泛型類,而LocalDataStoreSlot不是)。

  • static ThreadLocal<int> local = new ThreadLocal<int>(() => 123);??
  • static void Main()??
  • {??
  • //輸出本地線程TLS數據值
  • ??? Console.WriteLine(local.Value);??
  • //輸出另一個線程TLS數據值
  • ??? ThreadPool.QueueUserWorkItem(_ => Console.WriteLine(local.Value));??
  • //控制臺等待線程結束
  • ??? Console.ReadKey();??
  • }?
  • 輸出:
    123
    123

    ?

    這篇文章也可以參考

    http://www.cnblogs.com/lulu/archive/2012/03/17/2403872.html

    轉載于:https://www.cnblogs.com/chenqingwei/p/5003688.html

    總結

    以上是生活随笔為你收集整理的多线程中Local Store Slot(本地存储槽)[转]的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。