Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
volatile Gunakan kata kunci untuk menunjukkan bahwa bidang mungkin dimodifikasi oleh beberapa utas yang dijalankan secara bersamaan. Untuk alasan performa, pengkompilasi, sistem runtime, dan bahkan perangkat keras dapat mengatur ulang baca dan tulis ke lokasi memori. Mendeklarasikan bidang sebagai volatile mengecualikannya dari jenis pengoptimalan tertentu. Tidak ada jaminan dari satu total urutan penulisan volatil seperti yang terlihat dari semua utas eksekusi. Untuk informasi selengkapnya, lihat kelas Volatile.
Perhatian
Kata volatile kunci sering disalahpahami dan disalahgunakan dalam pemrograman multithreaded. Dalam sebagian besar skenario, gunakan alternatif yang lebih aman dan lebih dapat diandalkan alih-alih volatile. .NET modern menyediakan alat konkurensi yang lebih baik seperti kelas Interlocked, pernyataan lock, atau primitif sinkronisasi tingkat tinggi. Alternatif ini memberikan semantik yang lebih jelas dan jaminan yang lebih kuat daripada volatile. Pertimbangkan untuk hanya menggunakan volatile dalam skenario tingkat lanjut yang jarang terjadi di mana Anda sepenuhnya memahami batasannya dan telah memverifikasi bahwa ini adalah solusi yang sesuai.
Nota
Pada sistem multiprosesor, operasi baca volatil tidak menjamin untuk mendapatkan nilai terbaru yang ditulis ke lokasi memori tersebut oleh prosesor apa pun. Demikian pula, operasi penulisan volatil tidak menjamin bahwa nilai yang ditulis segera terlihat oleh prosesor lain.
Referensi bahasa C# mendokumentasikan versi bahasa C# yang paling baru dirilis. Ini juga berisi dokumentasi awal untuk fitur dalam pratinjau publik untuk rilis bahasa yang akan datang.
Dokumentasi mengidentifikasi fitur apa pun yang pertama kali diperkenalkan dalam tiga versi terakhir bahasa atau dalam pratinjau publik saat ini.
Petunjuk / Saran
Untuk menemukan kapan fitur pertama kali diperkenalkan di C#, lihat artikel tentang riwayat versi bahasa C#.
Terapkan volatile kata kunci ke bidang jenis ini:
- Jenis referensi.
- Jenis penunjuk (dalam konteks yang tidak aman). Meskipun pointer itu sendiri bisa volatil, objek yang ditujukannya tidak bisa. Dengan kata lain, Anda tidak dapat mendeklarasikan "pointer to volatile."
- Jenis sederhana seperti
sbyte, ,byte,shortushort,int, ,uint,char,float, danbool. - Jenis
enumdengan salah satu jenis dasar berikut:byte, ,sbyte,short,ushort,intatauuint. - Parameter jenis generik yang diketahui sebagai jenis referensi.
- IntPtr dan UIntPtr.
Anda tidak dapat menandai jenis lain, termasuk double dan long, karena volatile membaca dan menulis ke bidang jenis tersebut tidak dapat dijamin sebagai atomik. Untuk melindungi akses multithreaded ke jenis bidang tersebut Interlocked , gunakan anggota kelas atau lindungi akses dengan menggunakan lock pernyataan .
Untuk sebagian besar skenario multithreaded, bahkan dengan tipe yang didukung, lebih dianjurkan untuk menggunakan operasi Interlocked, statement lock, atau primitif sinkronisasi lainnya alih-alih volatile. Alternatif ini kurang rentan terhadap bug konkurensi yang sembunyi.
Anda hanya dapat menerapkan volatile kata kunci ke bidang class atau struct. Anda tidak dapat mendeklarasikan variabel lokal sebagai volatile.
Alternatif untuk volatile
Dalam kebanyakan kasus, gunakan salah satu alternatif yang lebih aman ini alih-alih volatile:
-
Interlocked operations: Menyediakan operasi atom untuk jenis numerik dan penetapan referensi. Operasi ini umumnya lebih cepat dan memberikan jaminan yang lebih kuat daripada
volatile. -
lockpernyataan: Memberikan pengecualian bersama dan hambatan memori. Gunakan untuk melindungi bagian penting yang lebih besar. -
Volatile kelas: Menyediakan operasi baca dan tulis volatil eksplisit dengan semantik yang lebih jelas daripada
volatilekata kunci. - Primitif sinkronisasi tingkat lebih tinggi: Seperti ReaderWriterLockSlim, , Semaphoreatau koleksi bersamaan dari System.Collections.Concurrent.
Kata volatile kunci tidak memberikan atomitas untuk operasi selain penugasan. Ini tidak mencegah kondisi balapan, dan tidak memberikan jaminan pemesanan untuk operasi memori lainnya. Batasan ini membuatnya tidak cocok untuk sebagian besar skenario konkurensi.
Contoh berikut menunjukkan cara mendeklarasikan variabel bidang publik sebagai volatile.
class VolatileTest
{
public volatile int sharedStorage;
public void Test(int i)
{
sharedStorage = i;
}
}
Contoh berikut menunjukkan bagaimana utas tambahan atau pekerja dapat dibuat dan digunakan untuk melakukan pemrosesan secara paralel dengan utas utama. Untuk informasi selengkapnya tentang multithreading, lihat Utas Terkelola.
public class Worker
{
// This method is called when the thread is started.
public void DoWork()
{
bool work = false;
while (!_shouldStop)
{
work = !work; // simulate some work
}
Console.WriteLine("Worker thread: terminating gracefully.");
}
public void RequestStop()
{
_shouldStop = true;
}
// Keyword volatile is used as a hint to the compiler that this data
// member is accessed by multiple threads.
private volatile bool _shouldStop;
}
public class WorkerThreadExample
{
public static void Main()
{
// Create the worker thread object. This does not start the thread.
Worker workerObject = new Worker();
Thread workerThread = new Thread(workerObject.DoWork);
// Start the worker thread.
workerThread.Start();
Console.WriteLine("Main thread: starting worker thread...");
// Loop until the worker thread activates.
while (!workerThread.IsAlive)
;
// Put the main thread to sleep for 500 milliseconds to
// allow the worker thread to do some work.
Thread.Sleep(500);
// Request that the worker thread stop itself.
workerObject.RequestStop();
// Use the Thread.Join method to block the current thread
// until the object's thread terminates.
workerThread.Join();
Console.WriteLine("Main thread: worker thread has terminated.");
}
// Sample output:
// Main thread: starting worker thread...
// Worker thread: terminating gracefully.
// Main thread: worker thread has terminated.
}
Ketika Anda menambahkan pengubah volatile ke deklarasi _shouldStop, Anda selalu mendapatkan hasil yang sama (mirip dengan kutipan yang ditampilkan dalam kode sebelumnya). Namun, tanpa pengubah itu pada _shouldStop anggota, perilaku tersebut tidak dapat diprediksi. Metode ini DoWork mungkin mengoptimalkan akses anggota, yang mengakibatkan pembacaan data kedaluarsa. Karena sifat pemrograman multithreaded, jumlah bacaan basi tidak dapat diprediksi. Eksekusi program yang berbeda menghasilkan hasil yang agak berbeda.
Spesifikasi bahasa C#
Untuk informasi selengkapnya, lihat Spesifikasi Bahasa C#. Spesifikasi bahasa adalah sumber definitif untuk sintaks dan penggunaan C#.