27 Şubat 2018 Salı

volatile Anahtar Kelimesi

Volatile
Volatile C++ ve Java'da farklı manalara gelir. Java ve C#'ta volatile kelimesi multithreading için kullanılır. Başka bir yerde işe yaramaz. Açıklaması şöyle.
volatile keyword guarantees visibility of shared state among multiple threads whenever there is a change.
Java'da çalışma prensibini açıklayan bir yazı burada.

Yazma İşlemi
Yazma işlemini tek bir thread'in yapması doğrudur. Açıklaması şöyle.
volatile keyword works well if there is only one writing thread.
Eğer iki thread aynı anda yazma yapıyorsa bir tanesinin yazdığı ezilir. Açıklaması şöyle.
If there are 2 or more writing threads, race condition will happen: all writing threads get the latest version of variable, modify value at its own CPU, then write to main memory. The consequence is that data in memory is just the output of one thread, other threads' modification were overridden.
Volatile bir değişkene yazma işlemi gerçekleşince diğer tüm thread'lerin en son değeri göreceği garanti edilir. Bunun nasıl gerçekleşeceği ise açık değil.

Bariyer kullanarak şöyle yapılır. Her yazma işleminden sonra bir store bariyeri kullanılır. Böylece yazılan değeri diğer işlemciler de görebilirler.

Okuma İşlemi
Bariyer kullanarak şöyle yapılır. Her okuma işleminden önce bir load (acquire) bariyeri kullanılır. Böylece diğer işlemcilerin yazdıkları değerler görülebilir.

Volatile ve Final
Volatile ve final mantık olarak bir araya gelemeyeceği için derleyici hata verir. final değerin değişmeyeceğini belirtir. Volatile ise değişebileceğini belirtir. Dolayısıyla çelişirler.
private final volatile AtomicInteger size; //1, Not compile
Örnek
Şöyle yaparız. ConcurrentHashSet değişkeninin kendisi yeniden yaratılınca volatile olduğu için diğer thread'ler de yeni değişkeni görebilir.
public class Test {

  private volatile Set<Integer> cache = Sets.newConcurrentHashSet();

  // multiple threads call this
  public boolean contain(int num) {
    return cache.contains(num);
  }

  // background thread periodically calls this
  private void refresh() {
    Set<Integer> newSet = getNums();
    cache = newSet; // is this assignment thread safe?
  }

  private Set<Integer> getNums() {
    Set<Integer> newSet = Sets.newConcurrentHashSet();
    // read numbers from file and add them to newSet
    return newSet;
  }
}


Hiç yorum yok:

Yorum Gönder