Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

Java 9에서 정적 VarHandle 생성하는 방법

VarHandle이란?

VarHandle은 변수에 대한 참조(reference)로, 일반(plain) 읽기/쓰기, volatile 읽기/쓰기, compare-and-swap(CAS)과 같은 다양한 접근 모드(access mode)를 통해 변수에 안전하게 접근할 수 있도록 해주는 기능입니다. 기존의 java.util.concurrent.atomic 패키지나 sun.misc.Unsafe가 제공하던 기능과 유사하지만, 표준 API로서 더 안전하고 명확한 방식으로 동시성 제어를 구현할 수 있습니다.

VarHandle이 참조할 수 있는 대상은 배열 요소, 클래스의 인스턴스 필드, 그리고 정적(static) 필드입니다.

정적 VarHandle 생성 예제

아래 예제에서는 정적 변수 핸들(static variable handle)을 생성하는 방법을 살펴봅니다. MethodHandles.lookup().in()으로 Lookup 객체를 얻은 뒤 findStaticVarHandle() 메서드를 호출하면 정적 필드에 대한 VarHandle을 만들 수 있으며, 배열 요소에 대해서는 MethodHandles.arrayElementVarHandle()을 사용합니다.

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;

public class StaticVarHandleTest {
   static int field;
   static int[] array = new int[20];
   static final VarHandle FIELD, ARRAY;
   static {
      try {
         FIELD = MethodHandles.lookup().in(StaticVarHandleTest.class).findStaticVarHandle(StaticVarHandleTest.class, "field", Integer.TYPE);
         ARRAY = MethodHandles.arrayElementVarHandle(int[].class);
      } catch(Exception e) {
         throw new InternalError(e);
      }
   }
   public static void main(String args[]) throws Exception {
      int i = (int)FIELD.getVolatile();
      System.out.println(i);
      FIELD.getAndAdd(5);
      System.out.println(field);
      System.out.println(ARRAY.getAndAdd(array, 5, 5));
      System.out.println(ARRAY.getAndAdd(array, 5, 5));
   }
}

실행 결과

0
5
0
5

결과 분석

  • FIELD.getVolatile(): 초기값 0을 volatile 모드로 읽어 출력합니다.
  • FIELD.getAndAdd(5): 정적 필드에 5를 더해 값이 5가 됩니다.
  • ARRAY.getAndAdd(array, 5, 5): 인덱스 5의 이전 값(0)을 반환한 후 5를 더합니다.
  • 두 번째 호출 시에는 이미 5가 저장되어 있으므로 이전 값인 5가 반환됩니다.

이처럼 VarHandle을 활용하면 원자적 연산과 volatile 의미론을 표준 API 기반으로 손쉽게 적용할 수 있습니다.