четверг, 9 августа 2012 г.

Синхронизация одной переменной в языке Java

В языке Java для атомарной работы с одной переменной в многопоточном приложении существуют несколько способов. Напрмер можно использовать обобщённый способ, который подходит не только для атомарного доступа к переменной, но и для других целей. Это использование блоков или методов synchronized, например так:

public class Test2 extends Thread {
 
 public Test2(String name){
  super(name);
 }
 
 public synchronized static void incrementCount(){
  count++;
 }
 
 @Override
 public void run(){
  int sleepTime = 0;
  for(int i = 0; i < 100; i++){
   sleepTime = (int)(Math.random()*10);
   try {
    sleep(sleepTime);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   incrementCount();
  }
 }
 
 public static int getCount(){
  return count;
 }
 
 private static int count = 0; 
}

Но в языке Java для атомарного доступа к одной переменной существует более элегантный способ. Это классы пакета java.util.concurrent.atomic. Напрмер для целочисленной переменной код будет выглядеть вот так:

import java.util.concurrent.atomic.AtomicInteger;

public class Test4 extends Thread {
  
 public Test4(String name){
  super(name);
 }
 
 @Override
 public void run(){
  int sleepTime = 0;
  for(int i = 0; i < 100; i++){
   sleepTime = (int)(Math.random()*10);
   try {
    sleep(sleepTime);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   count.incrementAndGet();
  }
 }
 
 public static int getCount(){
  return count.intValue();
 }

 private final static AtomicInteger count = new AtomicInteger(0);
}