17 Kasım 2019 Pazar

Thread Safety HashMap

Merhaba,
Bu yazida thread safe hashmap ile ilgili ornek yapacagiz.
Once thread safe olmayan bir ornek yapalim.

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class UnsafeMap {
 public static void main(String[] args) throws InterruptedException {
  Map cricketMap = new HashMap();
  cricketMap.put("Australia", 349);
  cricketMap.put("India", 257);
  ExecutorService executorService = Executors.newFixedThreadPool(10);
  Runnable task = new Runnable() {
   @Override
   public void run() {
    incrementScore(cricketMap, "India");
   }
  };
  for(int i=0; i<100 :="" ap="" cricketmap.get="" executorservice.awaittermination="" executorservice.shutdown="" executorservice.submit="" i="" inal="" incrementscore="" india="" integer="" is="" ndia="" of="" private="" score="" static="" system.out.println="" task="" timeunit.seconds="" tring="" void=""> teamMap, String team) {
  Integer score = teamMap.get(team);
  teamMap.put(team, score +1);
 }
}

Yukaridaki ornekte India nin score unu 100 arttirdik. Sonucun 258 olmasini bekliyoruz ama her seferinde baska sonuc cikiyor.

Final score of India is : 353
Final score of India is : 352

gibi. Neden ?

Cunku 

since multiple threads try to modify the HashMap concurrently, the change done by one thread gets overridden by some other thread, and the output becomes non-deterministic.

Bunu onlemek icinse ornegimizi thread safe yapalim. Yani sadece ayni anda tek bir thread erisebilsin. Bunun icin yapacagimiz iki sey sunlar olmali :

  • Use the Collections.synchronizedMap() method to obtain a synchronized view of the HashMap.
  • Write the increment logic inside a synchronized block.
Son halde kodumuz su sekilde olur:

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Safemap {
 public static void main(String[] args) throws InterruptedException {
  Map cricketScore = Collections.synchronizedMap(new HashMap());  
  cricketScore.put("Turkey", 52);
  cricketScore.put("Germany", 170);   
  //we are creating thread pool with size 10
  ExecutorService executorService = Executors.newFixedThreadPool(10);
  
  Runnable task = new Runnable() {   
   @Override
   public void run() {
    incrementScore(cricketScore, "Turkey");    
   }
  };
  for(int i=0; i<100 :="" ap="" cricketscore.get="" executorservice.awaittermination="" executorservice.shutdown="" executorservice.submit="" i="" inal="" incrementscore="" integer="" is="" of="" private="" score="" static="" system.out.println="" task="" timeunit.seconds="" tring="" turkey="" urkey="" void=""> scoreMap, String team) {
  synchronized (scoreMap) {
   Integer score = scoreMap.get(team);
   scoreMap.put(team, score +1);
  }
 }
}
Turkiyenin score unu 100 arttirdik. Threas safe oldugu icin her zaman 152 donecektir.

Final score of Turkey is : 152

Hiç yorum yok:

Yorum Gönder