Join, Synchronized

Kategori: Java , 19 Temmuz 2019 , JanFranco


Bu yazımızda senkronizasyon kavramından bahsedeceğim. Örnek üzerinden gitmek gerekirse, elimizde count isimli bir değişken olsun. Eğer 2 thread oluşturup, her bir threadde count değişkeninin değerini artırırsak bir for döngüsüyle, ve bu for döngüsü her iki threadde de 5000 iteration yaparsa, sonucu 10000 göremeyebiliriz. Bunu daha iyi açıklayabilmem için Threadlerden birine t1, diğerine t2 diyelim. t1 ve t2 aynı anda çalışmaya başladılar, count değeri 0. t1 count değerini bir artırırken aynı anda t2 de count değerini bir artırdı. t1 count değerini bir artırırken, 0 + 1 = 1 işlemi yapıldı. Ancak t2, t1 ile aynı anda işe başladığı için, işe başladığı anda count değeri 0'dı. t2 de 0 + 1 işlemini yaptı. Bu durumda sonuç 2 yerine 1 çıkmış oldu. İşte bu durumu engellemek için senkronizasyon kullanabiliriz. Şimdi bu anlattığım durumu kod üzerinden görelim:


public class Main_class {
	
	private int count = 0;
	
	public synchronized void increment() {
		count++;		
	}
	
	public void runThreads() {
		
		Thread thread1 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				for(int i=0; i<5000; i++) {
					increment();
				}
			}
		});
		
		Thread thread2 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				for(int i=0; i<5000; i++) {
					increment();
				}
			}
		});
		
		thread1.start();
		thread2.start();
		
		try {
			thread1.join();
			thread2.join();
		} catch (InterruptedException e) {
			System.out.println("Interrupted...");
		}
		
		System.out.println("Count : " + count);
		
	}
	
	public static void main(String[] args){
		
		Main_class class1 = new Main_class();
		
		class1.runThreads();
		
	}
	
}
Tüm kodu açıklayacağım fakat önce sonucu görelim:

Count : 10000
İlk olarak join methodu ile başlayalım. main methodu aynı zamanda kendi içinde bir thread barındırır. Bu kodları çalıştırdığımızda aynı anda 3 thread (main, thread1, thread2) çalışmaya başlarsa count değeri 0 gözükür. Çünkü count 0 iken main çalışır ve ekrana bastırır, program sonlanır. Ancak thread1 ve thread2'nin çalışmasını daha sonra main methodunun çalışmasını istiyorsak thread1.join(), thread2.join() methodlarını kullanabiliriz. Böylece thread1 ve thread2 işlemleri bittikten sonra main methodu çalışmış olur.

Senkronizasyon olayından bahsetmiştik. Eğer synchronized anahtar kelimesini kullanmamış olsaydık output değerimiz 1000 değil daha farklı değerler gelecekti. Bunun sebebi, thread1 çalışmaya başlar, count değerini alır (0 olsun) bir artırır ve yerine geri koyar. Ancak thread1 count 0 iken değeri aldığında, thread2 de çalışmaya başlarsa, thread2 de count değerini 0 alır. Thread1 önce aldığı için count değerini önce 1 artırır ve yerine koyar, daha sonra thread2 de bir artırıp yerine koyduğunda (0 + 1 = 1) output değeri 2 yerine 1 çıkar. Bunu engellemek için thread1 ve thread2 deki count++ kodunu silip, increment() şeklinde bir method yazdık. Methodun başına da synchronized anahtar kelimesini ekledik. Bunun anlamı thread1 ve thread2'den hangisi anahtara sahipse, methodu o çalıştırır. Yani thread1'de anahtar (lock) oluşur, methoda girer ve işini bitirip çıkar. Daha sonra anahtarı thread2'ye verir. Thread2 methoda girer ve işini yapar. Bu böyle veya farklı sıralarla devam eder. Böylece thread1 ve thread2 aynı anda methoda girmez ve sonuç olarak da output değeri 1000 çıkar.


Sonraki Yazı: Multiple Locks
Yorumlar

Henüz bir yorum bulunmuyor.
Yorum bırakın