달력

1

« 2021/1 »

  •  
  •  
  •  
  •  
  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  •  
  •  
  •  
  •  
  •  
  •  
2012. 11. 20. 17:00

Java volatile 키워드 정리. Java2012. 11. 20. 17:00

Java Language Specification 에 나온 내용을 기반으로 설명함.

 

8.3.1.4 volatile Fields


The Java programming language allows threads to access shared variables (§17.1).
As a rule, to ensure that shared variables are consistently and reliably updated, a
thread should ensure that it has exclusive use of such variables by obtaining a lock
that, conventionally, enforces mutual exclusion for those shared variables.
The Java programming language provides a second mechanism, volatile fields,
that is more convenient than locking for some purposes.
A field may be declared volatile, in which case the Java Memory Model ensures
that all threads see a consistent value for the variable (§17.4).8.3.1 Field Modifiers CLASSES

It is a compile-time error if a final variable is also declared volatile.

 

일단 위를 번역, 의역해보자..

 

자바는 thread 들이 공유된 변수에 접근하는 것을 허용한다.
일반적으로는(Java 뿐 아닌 다른 언어에 대해서도), Thread 간에 공유된 변수들의 일관성 있고 확실한 업데이트(데이터의 변경)를 하기 위해,

thread 는 이러한 변수들을 독점적으로 얻기 위한 방법으로 mutex 를 적용하곤 했다.

(여러 Thread 가 같은 변수에 한번에 접근하지 않기 위해서 Mutual Exclusion 처리를 해주고 있다는 말임.)


자바에서는 이에대해 좀더 쉬운 방법인 volatile field 라는 또 다른 방식을 제공한다.
field 가 volatile 을 이용해서 선언이 되었을 경우에,

자바 메모리 모델은 해당 변수에 대해 모든 쓰레드가 일관된 값을 사용할 것을 보장한다.
만약에 final 과 volatile 혼용해서 쓴다면 컴파일 시점에 오류가 발생하게 된다.

 

좀더 자세히 살펴보자..

 

1. Thread 간에 변수가 공유되면, Thread 는 그 값을 복사해 놓은 후, 복사한 값을 참조해서 사용한다.


Java 에서는 Thread 를 사용할 때 performance 향상을 위해 해당 변수의 값을

Thread 가 사용하는 메모리 영역에 caching 하는 것을 허용한다.


예를 들면, ThreadA 와 ThreadB 라는 두개의 쓰레드가 foo 라는 변수를 바라보고 있을 때,

foo 라는 변수를 각각 쓰레드의 로컬 메모리영역에 caching 해서 사용을 하는 식이 된다.


따라서, ThreadA 가 foo 라는 변수의 값을 "abc" 에서 "def" 로 바꾼다고 하더라도

어느 시점에는 ThreadB 는 여전히 "abc" 라는 값을 가지고 있을 수 있다.

(간단한 테스트 코드로도 확인 가능하다.)

 

이러한 문제를 극복하기 위해 volatile 이라는 키워드를 사용해서 변수를 선언하게 되면,

각 Thread 들은 foo를 caching 하지 않고, foo를 사용할 때마다 메인메모리 영역의 foo 를 바라본다.

위 글을 읽다 보면 final 과 volatile 은 같이 사용이 불가능 하다는 구문이 나오는데,

내 생각에는 final 은 변수가 바뀌지 않는다는 것을 전제도 하는 키워드이지만,

volatile 은 변수가 바뀌는 것을 전제로 하는 키워드이기 때문에 둘을 혼용해서 쓸 수 없는 것 같다.

2. Thread 간에 공유된 변수에 한 Thread 가 접근하면, 다른 Thread 는 접근하지 못한다.

 

예를들면 4바이트 이상의 변수인 long 을 변경한다고 했을 때, 앞 4바이트와 뒤 4바이트를 나눠서 변경한다.

예를들면 long 값을 21521542 에서 463634110 으로 변경시킨다고 했을 때, 앞 4바이트를 변경하고 뒤 4바이트를 변경한다.

 

이게 어떤 결과를 야기시킬 수 있냐면, 

여러 ThreadA 가 long 값을 변경시키고 있는 와중에도 ThreadB 가 long 에 접근하면,

ThreadB 는 21521542 도 아니고 463634110 도 아닌 전혀 다른 값을 출력할 수 있다는 얘기다.

 

그 값의 정체는 앞4바이트 값은 바뀌고 있는데 뒤 4바이트는 예전의 값인, 두 숫자가 혼합된 값이 나올수도 있다는 얘기다.

(int 같은 경우에는 어차피 4바이트 변수니까 해당사항이 없긴 하다.)

 

내가 알아본 volatile 키워드의 효과는 위에 적은 두가지다.

까먹지 말고 잘 사용합시다~ :)

Posted by maruldy

댓글을 달아 주세요

TimeZone.getDefault().getOffset(기준시간); 로 값을 얻어오면
offset 을 얻을 수 있는데 이게 역시 currentTimeMillis 로 들어온다.

이걸 기준시간에 더해버리면 현재 지역의 시간을 얻을 수 있다.

Posted by maruldy

댓글을 달아 주세요

2012. 1. 12. 10:32

SimpleDateFormat 예제 Java2012. 1. 12. 10:32



  // 년도, 월, 날짜만 출력
  SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd");
  simpleDateFormat.format(msgDate);
  
  // 오전 또는 오후라고 나옴. ex) 오후
  SimpleDateFormat isAmFormat = new SimpleDateFormat("aa");
  isAmFormat.format(msgDate);
  
  // 시간, 분 출력 ex) 11:13
  SimpleDateFormat currentDateSimpleDateFormat = new SimpleDateFormat("hh:mm");
  currentDateSimpleDateFormat.format(currentDate);
Posted by maruldy

댓글을 달아 주세요


try {
   for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
                NetworkInterface intf = en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress()) {
                     inetAddress.getHostAddress().toString(); <-- 이거임.
                    }
                }
            }
  } catch (Exception e) {
   // TODO: handle exception
  }
Posted by maruldy

댓글을 달아 주세요

2010. 3. 22. 20:39

Delegation Java2010. 3. 22. 20:39

.Net 에서는 Delegation 을 지원해준다고 하던데 .Net 은 아직 공부 안해서 잘 모르겠다..
Java 에서는 Delegation 을 명시적으로(키워드로) 원하지는 않는다.

Java 에서 구현하는 Delegation은

직접 A 클래스를 상속받지 않고서 그 클래스의 기능을
B 클래스에서 사용 가능하도록 A 클래스의 객체를 포함시킨다.(Composition)

B 클래스에서는, 사용하고싶은 A클래스의 메소드를 B 클래스 안에 구현해놓고 그것을 사용하기만 하면
결과적으로 메소드를 통한 인터페이스는 상속과 동일하게 된다. 

결과적으로 필요한것만 그때그때 사용할 수 있다는 점에서 더 강력한 기능을 할 수 있게 된다.

그런데.. 궁금한게 갑자기 생겼는데, 팀 프로젝트로 진행할때 이걸 쓸 일이 있을까?
interface 를 이용하는것과 별반 다를바가 없어보이는데..
.....에라 일단 알고 보는거다.. -_-; 알아서 나쁠거 없잖아.. ㅜ.ㅜ;; 나중에 이사람 저사람 물어보지 머..

..생각해봤는데 interface 와 이것과는 많은 차이가 있네... 아..이래서 머리나쁘면 고생..ㅠㅠ

Posted by maruldy

댓글을 달아 주세요

2010. 3. 17. 18:49

Composition 과 Inheritance Java2010. 3. 17. 18:49


Composition 과 Inheritance 의 차이는,

Class Father {
   public void gaming() {
      System.out.println("exciting!");
   }
}

Class Son extends Father {
   @Override
   public void gaming() {
      System.out.println("lol!!!");
      super.gaming();
   }
   public static void main(String[] args) {
      Son son = new Son();
      son.gaming();
   }
}
결과:
lol!!
exciting!

이렇게 사용하는것이 상속이고,

Composition 은 TIJ 로 공부하다가 이 말이 나오길래.. 뭔가 했더니..
별다른거 없었네..ㅜ.ㅜ;

Class Father {
   public void gaming() {
      System.out.println("exciting!");
   }
}

Class Son {
   public static void main(String[] args) {
      Father father = new Father();
      father.gaming();
   }
}

처럼 클래스에서 다른 클래스의 객체를 생성해서 사용하는것이 Composition..
Posted by maruldy

댓글을 달아 주세요

2010. 3. 17. 16:08

초기화와 static.. Java2010. 3. 17. 16:08

공부했던것 중에 중요한 부분을 Blog 에다가 적어놓으면 왠지 안잊어먹을것 같고,
실제로도 적으면서 좀더 정리를 잘 시킬수 있어서 좋은것 같다.
그러니까... 나의 적은 게으름이다!!! ;;

전에 Java 를 공부할 때 static 의 경우에는 조금 특별하게 생각해야 한다고 공부했는데,
이번에 다시 책을 보면서 공부하는 도중에 static 이 눈에 띄길래 천천히 읽어보았다.
초기화 시에, static 필드로 참조되는 객체에 대해서 어떤점을 주의해야 할까 읽어보니까,

1. non-static 객체가 static 객체보다 먼저 정의되어 있더라도, static 객체가 먼저 초기화된다.
2. static 객체는 처음 한번만 초기화된다.

의 두가지가 초기화와 관련해서 눈에 가장 먼저 들어왔고..

접근제한자와 static 을 이용한 Singleton 패턴을 사용할때도 눈에 들어왔다.
Singleton 패턴은... 에.. 나중에 Design Pattern 카테고리에서 한방에 패턴들 모아서 정리를..^^; 
Posted by maruldy

댓글을 달아 주세요

2010. 3. 8. 18:06

this 키워드. Java2010. 3. 8. 18:06

public class Cat {
   private int height;
   private int age;

   public int getHeight() {
        return heght;
   }
  
   public void setHeight(int height) {
        this.height = height;
   }

...... 이하생략
}

나같은 학생은 위에서 사용할때와 크게 벗어나지 않는 선에서 this 를 사용해왔는데,
Thinking in Java 를 처음부터 다시 천천히 보고 있는데,
이 책이 나에게 this 에 대한 개념정리를 다시 시켜주었다.

// "this" 키워드의 간단한 예

public class Leaf {
 
 int i;
 
 // return this; 는 사용한 객체의 참조를 반환한다.
 Leaf increment() {
  i++;
  return this;
 }
 
 void print() {
  System.out.println("i = " + i);
 }
 
 public static void main(String[] args) {
  Leaf leaf = new Leaf();
  leaf.increment().increment().increment().print(); 
 }
}

위와 같은 방식으로 현재의 객체를 반환하기 때문에 leaf.increment().increment().increment().print();
와 같은 방식으로 코딩을 할 수 있다. 

다른 쓰임새 로는, 다른 메소드로 객체를 전달할 때도, this 키워드를 사용할 수 있다.

또한 '생성자'를 오버로딩 한 클래스에서, 다른 '생성자' 를 호출할 때, 한번만 사용할 수 있다.
Car(String s, int i) {
   this(i);
}
// 위의 생성자는 아래의 생성자를 호출하게 된다.
Car(int i) {
  ....
}

한번만 사용할 수 있다고 했는데, 여러번 사용하고 싶으면 this 를 이용한 instance variable 을 직접 조작해야한다.
예를들면 this.i = i 와 같이..

TAG Java, this
Posted by maruldy

댓글을 달아 주세요