Dengan kata lain, apakah thread implementasi Singleton ini aman:
public class Singleton
{
private static Singleton instance;
private Singleton() { }
static Singleton()
{
instance = new Singleton();
}
public static Singleton Instance
{
get { return instance; }
}
}
c#
multithreading
singleton
urini
sumber
sumber
Instance
sekaligus. Salah satu utas akan diperintahkan untuk pertama kali menjalankan penginisialisasi tipe (juga dikenal sebagai konstruktor statis). Sementara itu semua utas lainnya yang ingin membacaInstance
properti, akan dikunci hingga jenis inisialisasi selesai. Hanya setelah inisialisasi bidang selesai, utas akan diizinkan untuk mendapatkanInstance
nilai. Jadi tidak ada yang bisa melihatInstance
keberadaannull
.X
akhirnya menjadi-1
bahkan tanpa threading . Ini bukan masalah keamanan thread. Alih-alih, penginisialisasix = -1
berjalan pertama (pada baris sebelumnya dalam kode, nomor baris lebih rendah). Kemudian inisialisasiX = GetX()
dijalankan, yang membuat huruf besarX
sama dengan-1
. Dan kemudian konstruktor statis "eksplisit", tipe initializerstatic C() { ... }
berjalan, yang hanya mengubah huruf kecilx
. Jadi setelah semua itu,Main
metode (atauOther
metode) dapat melanjutkan dan membaca huruf besarX
. Nilainya akan-1
, bahkan hanya dengan satu utas.Jawaban:
Konstruktor statis dijamin akan dijalankan hanya sekali per domain aplikasi, sebelum instance kelas dibuat atau anggota statis diakses. https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors
Implementasi yang ditunjukkan adalah thread aman untuk konstruksi awal, yaitu, tidak ada penguncian atau pengujian nol diperlukan untuk membangun objek Singleton. Namun, ini tidak berarti bahwa penggunaan instance akan disinkronkan. Ada berbagai cara yang bisa dilakukan; Saya telah menunjukkan satu di bawah ini.
sumber
Lazy<T>
- siapa pun yang menggunakan kode yang saya posting pada awalnya melakukan kesalahan (dan jujur itu tidak baik untuk memulai dengan - 5-tahun-lalu-saya tidak sebagus barang ini seperti saat ini -aku adalah :) ).Sementara semua jawaban ini memberikan jawaban umum yang sama, ada satu peringatan.
Ingat bahwa semua derivasi potensial dari kelas generik dikompilasi sebagai tipe individu. Jadi gunakan hati-hati ketika menerapkan konstruktor statis untuk tipe generik.
EDIT:
Inilah demonstrasi:
Di konsol:
sumber
Menggunakan konstruktor statis sebenarnya adalah threadsafe. Konstruktor statis dijamin akan dieksekusi hanya sekali.
Dari spesifikasi bahasa C # :
Jadi ya, Anda bisa percaya bahwa singleton Anda akan dipakai dengan benar.
Zooba membuat titik yang sangat baik (dan 15 detik sebelum saya juga!) Bahwa konstruktor statis tidak akan menjamin akses bersama aman-thread ke singleton. Itu perlu ditangani dengan cara lain.
sumber
Inilah versi Cliffnotes dari halaman MSDN di atas pada c # singleton:
Gunakan pola berikut, selalu, Anda tidak bisa salah:
Di luar fitur singleton yang jelas, ia memberi Anda dua hal ini secara gratis (sehubungan dengan singleton di c ++):
sumber
Konstruktor statis dijamin akan memecat hanya sekali per App Domain sehingga pendekatan Anda harus OK. Namun, secara fungsional tidak ada bedanya dengan versi inline yang lebih ringkas:
Keamanan utas lebih merupakan masalah ketika Anda malas menginisialisasi sesuatu.
sumber
Konstruktor statis akan selesai berjalan sebelum utas apa pun diizinkan untuk mengakses kelas.
Kode di atas menghasilkan hasil di bawah ini.
Meskipun konstruktor statis membutuhkan waktu lama untuk berjalan, utas lainnya berhenti dan menunggu. Semua utas membaca nilai _x yang ditetapkan di bagian bawah konstruktor statis.
sumber
The Common Language Spesifikasi Infrastruktur jaminan bahwa "jenis initializer akan dijalankan tepat sekali untuk setiap jenis tertentu, kecuali secara eksplisit disebut oleh kode pengguna." (Bagian 9.5.3.1.) Jadi, kecuali jika Anda memiliki beberapa IL yang aneh pada panggilan longgar Singleton :: .cctor secara langsung (tidak mungkin) konstruktor statis Anda akan berjalan tepat sekali sebelum tipe Singleton digunakan, hanya satu instance Singleton yang akan dibuat, dan properti Instance Anda aman-utas.
Perhatikan bahwa jika konstruktor Singleton mengakses properti Instance (bahkan secara tidak langsung) maka properti Instance akan menjadi nol. Yang terbaik yang dapat Anda lakukan adalah mendeteksi kapan ini terjadi dan melempar pengecualian, dengan memeriksa bahwa instance tersebut tidak nol di accessor properti. Setelah konstruktor statis Anda selesai, properti Instance akan menjadi non-null.
Seperti yang ditunjukkan oleh jawaban Zoomba, Anda perlu membuat Singleton aman untuk diakses dari banyak utas, atau menerapkan mekanisme penguncian dengan menggunakan instance singleton.
sumber
Hanya untuk menjadi bertele-tele, tetapi tidak ada yang namanya konstruktor statis, melainkan inisialisasi tipe statis, inilah demo kecil ketergantungan konstruktor statis siklik yang menggambarkan hal ini.
sumber
Konstruktor statis dijamin aman dari utas. Juga, lihat diskusi tentang Singleton di DeveloperZen: http://web.archive.org/web/20160404231134/http://www.developerzen.com/2007/07/15/whats-wrong-with-this-code-code -1-diskusi /
sumber
Meskipun jawaban lain sebagian besar benar, ada peringatan lain dengan konstruktor statis.
Sesuai bagian II.10.5.3.3 Ras dan kebuntuan dari ECMA-335 Common Language Infrastructure
Kode berikut ini menghasilkan jalan buntu
Penulis asli adalah Igor Ostrovsky, lihat jabatannya di sini .
sumber