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.
Kata volatile kunci menunjukkan bahwa bidang mungkin dimodifikasi oleh beberapa utas yang dijalankan secara bersamaan. Pengkompilasi, sistem runtime, dan bahkan perangkat keras dapat mengatur ulang baca dan tulis ke lokasi memori karena alasan performa. Bidang yang dideklarasikan volatile dikecualikan dari jenis pengoptimalan tertentu. Tidak ada jaminan adanya satu urutan tunggal dari penulisan memori volatil seperti yang terlihat dari perspektif semua utas eksekusi. Untuk informasi selengkapnya, lihat kelas Volatile.
Perhatian
Kata volatile kunci sering disalahpahami dan disalahgunakan dalam pemrograman multithreaded. Dalam kebanyakan skenario, Anda harus menggunakan alternatif yang lebih aman dan lebih andal 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 akan segera terlihat oleh prosesor lain.
Kata volatile kunci dapat diterapkan ke bidang jenis ini:
- Jenis referensi.
- Jenis penunjuk (dalam konteks yang tidak aman). Perhatikan bahwa meskipun penunjuk itu sendiri dapat volatil, objek yang ditujukannya tidak dapat. 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.
Jenis lain, termasuk double dan long, tidak dapat ditandai volatile karena membaca dan menulis ke bidang jenis tersebut tidak dapat dijamin sebagai atomik. Untuk melindungi akses multi-utas ke jenis bidang tersebut, gunakan anggota kelas Interlocked atau lindungi akses menggunakan pernyataan lock.
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.
Kata volatile kunci hanya dapat diterapkan ke bidang class atau struct. Variabel lokal tidak dapat dideklarasikan volatile.
Alternatif untuk volatile
Dalam kebanyakan kasus, Anda harus menggunakan salah satu alternatif yang lebih aman ini alih-alih volatile:
-
Interlocked operations: Menyediakan operasi atom untuk jenis numerik dan penetapan referensi. 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 atomisitas untuk operasi selain penugasan, tidak mencegah kondisi berlomba, dan tidak memberikan jaminan pengurutan untuk operasi memori lainnya. Batasan ini membuatnya tidak cocok untuk sebagian besar skenario konkurensi.
Contoh
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.
}
Dengan menambahkan pengubah volatile ke dalam deklarasi _shouldStop yang sudah ada, Anda akan selalu mendapatkan hasil yang sama (mirip dengan bagian yang ditunjukkan dalam kode sebelumnya). Namun, tanpa pengubah itu pada _shouldStop anggota, perilaku tersebut tidak dapat diprediksi. Metode DoWork dapat mengoptimalkan akses anggota, yang dapat menghasilkan pembacaan data usang. Karena sifat pemrograman multi-utas, jumlah bacaan basi tidak dapat diprediksi. Eksekusi program yang berbeda akan 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#.