ThreadStatic vs ThreadLocal <T>: apakah generik lebih baik daripada atribut?


Jawaban:


112

Sesuatu yang dicatat oleh posting blog di komentar tidak membuatnya eksplisit, tetapi menurut saya sangat penting, adalah itu [ThreadStatic]tidak secara otomatis menginisialisasi hal-hal untuk setiap utas. Misalnya, Anda memiliki ini:

[ThreadStatic]
private static int Foo = 42;

Utas pertama yang menggunakan ini akan melihat Foodiinisialisasi ke 42. Tetapi utas berikutnya tidak akan. Penginisialisasi hanya berfungsi untuk utas pertama. Jadi Anda akhirnya harus menulis kode untuk memeriksa apakah sudah diinisialisasi.

ThreadLocal<T> memecahkan masalah itu dengan membiarkan Anda menyediakan fungsi inisialisasi (seperti yang ditunjukkan blog Reed) yang dijalankan sebelum pertama kali item tersebut diakses.

Menurut pendapat saya, tidak ada keuntungan menggunakan [ThreadStatic]daripada ThreadLocal<T>.


20
Kecuali mungkin yang ThreadLocal<T>tersedia di NET 4 dan atas, dan yang ThreadStaticatribut juga tersedia dalam 3.5 dan bawah.
Jeroen

2
Dan jika Anda tidak menggunakan penginisialisasi untuk menyetel nilainya, tetapi malah menyetelnya di beberapa titik setelah inisialisasi, menggunakan [ThreadStatic] lebih bersih secara sintaksis.
Pikir

9
Dan kecuali yang ThreadLocal<T>menerapkan IDisposabledan biasanya memaksa Anda untuk menerapkan IDisposablejuga, yang memaksa penelepon Anda untuk membuang Anda dan karena itu menerapkannya IDisposablejuga ...
Stefan Steinegger

4
@StefanSteinegger: Saya akan sangat berhati-hati menggunakan ThreadLocalatau ThreadStaticdengan utas kumpulan. Nilai-nilai tersebut akan tetap ada sepanjang masa pakai utas kumpulan, tidak hanya untuk tugas yang Anda tetapkan. Itu dapat menyebabkan masalah bagi Anda dalam beberapa cara yang tidak terlalu jelas. Lihat stackoverflow.com/questions/561518/… dan pertanyaan serupa untuk info lebih lanjut.
Jim Mischel

3
Bukankah bidang dalam contoh juga harus dideklarasikan static? Lihat msdn.microsoft.com/en-us/library/…
entheh

39

ThreadStatic Inisialisasi hanya pada utas pertama, ThreadLocal Inisialisasi untuk setiap utas. Di bawah ini adalah demonstrasi sederhana:

    public static ThreadLocal<int> _threadlocal =
        new ThreadLocal<int>(() =>
        {
            return Thread.CurrentThread.ManagedThreadId;
        });

    public static void Main()
    {
        new Thread(() =>
        {
            for (int x = 0; x < _threadlocal.Value; x++)
            {
                Console.WriteLine("First Thread: {0}", x);
            }
        }).Start();

        new Thread(() =>
        {
            for (int x = 0; x < _threadlocal.Value; x++)
            {
                Console.WriteLine("Second Thread: {0}", x);
            }
        }).Start();

        Console.ReadKey();
    }

masukkan deskripsi gambar di sini


15

Ide utama di balik ThreadStatic adalah mempertahankan salinan variabel terpisah untuk setiap utas .

class Program
    {
        [ThreadStatic]
        static int value = 10;

        static void Main(string[] args)
        {
            value = 25;

            Task t1 = Task.Run(() =>
            {
                value++;
                Console.WriteLine("T1: " + value);
            });
            Task t2 = Task.Run(() =>
            {
                value++;
                Console.WriteLine("T2: " + value);
            });
            Task t3 = Task.Run(() =>
            {
                value++;
                Console.WriteLine("T3: " + value);
            });

            Console.WriteLine("Main Thread : " + value);

            Task.WaitAll(t1, t2, t3);
            Console.ReadKey();
        }
    }

Dalam cuplikan di atas, kami memiliki salinan terpisah valueuntuk setiap utas, termasuk utas utama.

masukkan deskripsi gambar di sini

Jadi, variabel ThreadStatic akan diinisialisasi ke nilai defaultnya di utas lain kecuali utas tempat ia dibuat.

Jika kita ingin menginisialisasi variabel pada setiap utas dengan cara kita sendiri, gunakan ThreadLocal.


1
Dan artikel lengkapnya bisa dilihat disini .
Daniel Dušek
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.