Java’da Multithreading – Bölüm 3: “synchronized” Anahtar Kelimesi

İkinci bölümde threadlerin senkronizasyonu sırasında karşılaştığımız zorlukların birincisinden bahsetmiştik. Bu bölümde bu zorlukların ikincisini ve onu aşmak için Java’nın bize sağladığı “synchronized” anahtar kelimesini kullanmayı örnekleyeceğiz. Önce zorluğun/problemin ne olduğunu yine bir örnek ile açıklamaya çalışalım:

public class Application {

    private int count = 0;

    public static void main(String[] args) {
        Application application = new Application();
        application.doCount();
    }

    private void doCount() {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10000; i++) {
                    count++;
                }
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10000; i++) {
                    count++;
                }
            }
        });

        thread1.start();
        thread2.start();

        System.out.println("Sayaç: " + count);
    }

}

“Application” sınıfının “count” (sayaç) adlı, başlangıç değeri 0 olan tam sayı tipinde bir örnek değişkeni vardır. “main” metodu içinde bir “Application” nesnesi oluşturarak “doCount()” çağrılır. “doCount()” metodu içinde, “run()” metodu içerisinde “count” değişkenini 10000 kere arttıracak birer döngü içeren iki thread oluşturulur ve başlatılır. Metodun sonunda ise “count” değişkeninin son değeri yazdırılır. Buraya kadar her şey açık. Ancak bu programı çalıştırdığımızda bizi bir sürpriz beklemektedir. Program sonlandığında konsolda 20000 görmeyi bekleyenlerimiz olacaktır. Evet bazen 20000 görebiliriz de. Ancak 511 gibi, 10987 gibi saçma sayılar gördüğünüzde siz de benim gibi şaşırmışsınızdır. Sebebi şudur: “thread1” ve “thread2” ayrı threadler oldukları için “start()” metotlarıyla başladıktan sonra ana thread, yani bu iki threadi başlatan o anki geçerli thread işleyişine devam eder ve “count” değişkeninin anlık değerini konsola yazdırır. Bu sırada “thread1” ve “thread2” sonlanmamış olabilecekleri için sayacın son değeri bazı durumlar için 20000 olamayabilir. Bu durumu çözmek için bu iki threadin “join()” metodunu çağırarak threadlere, çalışmaları bitene kadar “geçerli threadi” bekletmelerini söyleyebiliriz: Okumaya devam et

Java’da Multithreading – Bölüm 2: Threadlerin Senkronizasyonuna Giriş

Aynı veri ile ilgilenen birden fazla threadin veriye erişiminin düzenlenmesine threadlerin senkronizasyonu denir. Threadlerin senkronizasyonu sırasında karşılaştığımız zorlukların ilki bazı durumlarda verinin performans gerekçesiyle otomatik olarak önbelleklenmesidir (caching). Bir örnek ile üstesinden gelmemiz gereken bu durumu açıklayalım. Thread sınıfını genişleterek oluşturduğumuz Processor sınıfımız aşağıdaki gibi olsun:

class Processor extends Thread {

    private boolean running = true;

    @Override
    public void run() {
        while (running) {
            System.out.println("Merhaba");
        }
    }

}

“run()” metodunun içeriğini incelersek bu sınıftan bir örnek oluşturup “start()” metodunu çağırdığımızda başlatılacak olan threadin sonsuza kadar “Merhaba” yazdıracağını görebiliriz. Çünkü “running” değişkeni her zaman “true” değerindedir. Gelin yeni bir metot ekleyelim ve çağrıldığında  “running” değişkeninin değerini “false” yaparak “while” döngüsünü sonlandırmış olalım, dolayısıyla thread de sonlanmış olsun: Okumaya devam et