Apakah ada aturan / pedoman keseluruhan untuk apa yang membuat metode thread-safe? Saya mengerti bahwa mungkin ada sejuta situasi, tetapi bagaimana dengan secara umum? Apakah ini sederhana?
- Jika metode hanya mengakses variabel lokal, itu aman untuk thread.
Itu saja? Apakah itu berlaku untuk metode statis juga?
Satu jawaban, diberikan oleh @Cybis, adalah:
Variabel lokal tidak dapat dibagi di antara utas karena setiap utas mendapat tumpukannya sendiri.
Apakah itu berlaku untuk metode statis juga?
Jika suatu metode dilewatkan objek referensi, apakah itu melanggar keselamatan thread? Saya telah melakukan beberapa penelitian, dan ada banyak di luar sana tentang kasus-kasus tertentu, tetapi saya berharap dapat mendefinisikan, dengan hanya menggunakan beberapa aturan, pedoman untuk mengikuti untuk memastikan metode aman thread.
Jadi, saya kira pertanyaan pamungkas saya adalah: "Apakah ada daftar pendek aturan yang menentukan metode thread-safe? Jika ya, apakah itu?"
EDIT
Banyak poin bagus telah dibuat di sini. Saya pikir jawaban sebenarnya untuk pertanyaan ini adalah: "Tidak ada aturan sederhana untuk memastikan keamanan thread." Keren. Baik. Tetapi secara umum saya pikir jawaban yang diterima memberikan ringkasan pendek yang bagus. Selalu ada pengecualian. Jadilah itu. Saya bisa hidup dengan itu.
sumber
Jawaban:
Jika suatu metode (contoh atau statis) hanya mereferensikan variabel yang dicakup dalam metode itu, maka metode ini aman karena setiap utas memiliki tumpukan sendiri:
Dalam hal ini, beberapa utas dapat memanggil
ThreadSafeMethod
secara bersamaan tanpa masalah.Ini juga benar jika metode ini memanggil metode kelas lain yang hanya merujuk variabel cakupan lokal:
Jika metode mengakses properti (bidang objek) apa pun (bidang atau statis) maka Anda perlu menggunakan kunci untuk memastikan bahwa nilai-nilai tidak diubah oleh utas yang berbeda.
Anda harus menyadari bahwa setiap parameter yang diteruskan ke metode yang bukan merupakan struct atau tidak dapat diubah dapat dimutasi oleh utas lain di luar ruang lingkup metode.
Untuk memastikan konkurensi yang tepat, Anda perlu menggunakan penguncian.
untuk informasi lebih lanjut lihat referensi pernyataan kunci # C dan ReadWriterLockSlim .
kunci sebagian besar berguna untuk menyediakan fungsionalitas satu per satu,
ReadWriterLockSlim
berguna jika Anda membutuhkan banyak pembaca dan penulis tunggal.sumber
private string someValue;
tidakstatic
begitu setiap contoh akan mendapatkan salinan terpisah dari variabel itu. Jadi bisakah Anda menjelaskan bagaimana ini tidak aman?Thing
kelas yang diakses oleh banyak utasSama sekali tidak. Anda dapat menulis sebuah program dengan hanya satu variabel lokal yang diakses dari satu utas yang tidak utas:
https://stackoverflow.com/a/8883117/88656
Benar-benar tidak.
Benar-benar tidak. Karakteristik pembeda dari variabel lokal adalah bahwa itu hanya terlihat dari dalam lingkup lokal , bukan dialokasikan pada pool sementara . Sangat sah dan memungkinkan untuk mengakses variabel lokal yang sama dari dua utas yang berbeda. Anda dapat melakukannya dengan menggunakan metode anonim, lambdas, blok iterator, atau metode async.
Benar-benar tidak.
Mungkin.
Anda harus belajar hidup dengan kekecewaan. Ini adalah subjek yang sangat sulit.
Nggak. Seperti yang Anda lihat dari contoh saya sebelumnya, metode kosong dapat menjadi non-thread-safe . Anda mungkin juga bertanya "apakah ada daftar pendek aturan yang memastikan metode itu benar ". Tidak, tidak ada. Keamanan benang tidak lebih dari jenis kebenaran yang sangat rumit.
Selain itu, fakta bahwa Anda mengajukan pertanyaan menunjukkan kesalahpahaman mendasar Anda tentang keamanan benang. Keamanan thread adalah global , bukan properti lokal dari suatu program. Alasan mengapa sangat sulit untuk mendapatkan yang benar adalah karena Anda harus memiliki pengetahuan lengkap tentang perilaku threading dari seluruh program untuk memastikan keamanannya.
Sekali lagi, lihat contoh saya: setiap metode adalah sepele . Ini adalah cara metode berinteraksi satu sama lain pada tingkat "global" yang membuat kebuntuan program. Anda tidak dapat melihat setiap metode dan memeriksanya sebagai "aman" dan kemudian berharap bahwa seluruh program aman, lebih dari yang dapat Anda simpulkan bahwa karena rumah Anda terbuat dari 100% batu bata tidak berlubang, maka rumah tersebut juga tidak berlubang. Kekosongan sebuah rumah adalah properti global dari semuanya, bukan agregat dari properti bagian-bagiannya.
sumber
class C { public static Func<int> getter; public static Action<int> setter; public static void M() { int x = 0; getter = ()=>x; setter = y=>{x=y;};} }
Panggil M (), lalu panggil C.getter dan C.setter pada dua utas berbeda. Variabel lokal sekarang dapat ditulis dan dibaca dari dua utas yang berbeda meskipun itu adalah lokal. Sekali lagi: karakteristik yang menentukan dari variabel lokal adalah bahwa itu adalah lokal , bukan pada tumpukan thread .Tidak ada aturan yang keras dan cepat.
Berikut adalah beberapa aturan untuk membuat utas kode aman di .NET dan mengapa ini bukan aturan yang baik:
lock
pada hal yang sama. Semua kunci harus dilakukan dalam urutan yang sama. Ini akan membuat utas kode aman, tetapi akan sangat lambat, dan Anda mungkin juga tidak menggunakan banyak utas.Tidak ada aturan yang membuat utas kode aman, satu-satunya yang dapat Anda lakukan adalah memastikan bahwa kode Anda akan berfungsi tidak peduli berapa kali dieksekusi secara aktif, setiap utas dapat diinterupsi pada titik mana pun, dengan setiap utas berada di negara / lokasi sendiri, dan ini untuk setiap fungsi (statis atau lainnya) yang mengakses objek umum.
sumber
Itu harus disinkronkan, menggunakan kunci objek, stateless, atau tidak berubah.
tautan: http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html
sumber