일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 비트마스킹
- 이분 매칭
- 구간 트리
- Java
- 게이트웨이
- Gradle
- Logback
- 구현
- Zuul
- 메모이제이션
- 트리
- 도커
- 유레카
- 다익스트라
- ZuulFilter
- 달팽이
- 스프링 시큐리티
- Spring Cloud Config
- 이분 탐색
- docker-compose
- 플로이드 와샬
- 서비스 디스커버리
- 백트래킹
- spring boot
- BFS
- 주울
- 완전 탐색
- spring cloud
- 스택
- dp
- Today
- Total
Hello, Freakin world!
[Java] volatile에 대한 고찰(용도, 스레드 세이프, 실제적 쓰임) 본문
용도는?
volatile의 용도는 다중 스레드 프로그래밍에서 변수 메모리의 위치를 스레드의 로컬(위의 Working Memory)이 아니라 Main Memory에 생성함으로서 일관성있는 데이터의 참조가 가능한 변수를 만들기 위함입니다.
하지만 과연 스레드 세이프할까요?
스레드 세이프 한가?
만약 volatile을 적용한 변수에 대해서 읽고 쓰기만 한다면 스레드 세이프합니다.
하지만 volatile변수의 연산 결과를 로컬 변수에 저장하고, 다시 이 로컬 변수를 volatile변수에 할당하는 경우에
데이터의 일관성이 깨질 수 있습니다.
volatile int n = 1;
public void modify() {
int temp = n + 1;
n = temp;
}
위의 경우에서 n+1 연산을 하는 도중 다른 스레드에서 n 변수를 읽는다면 1을 가집니다.
이렇게 연산이 atomic 하지 않다면(연산이 둘 이상의 단계를 거친다면) 그 시간 차로 인해서 데이터의 일관성이 깨질 수 있습니다.
만약 값을 여러 단계에 걸쳐서 변경해야할 필요가 있다면, 로컬 변수를 사용하면 안됩니다.
모든 단계에서 volatile 변수에 직접 값을 할당해야 합니다.
volatile 변수를 스레드 내에서 변경해야할 필요가 있다면, volatile보단 자바에서 지원하는 concurrent.atomic 패키지의 클래스들을 살펴보세요.
그럼 쓸데가 없는거 아니냐?
아닙니다.
단순 플래그나 객체의 참조는 사용하는 목적에 따라서 volatile 변수를 유용하게 활용할 수 있습니다.
스레드에서 volatile 변수를 플래그로 사용하는 한 가지 예입니다.
public class WorkThread extends Thread{
volatile boolean runningFlag = true;
@Override
public void run() {
while(runningFlag) {
System.out.println("스레드 돌아가는 중");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void stopThread() {
runningFlag = false;
}
}
자바에서 stop 메서드가 안정성의 이유로 폐기되면서, 개발자는 스레드를 안전하게 종료하는 방법을 제공해야합니다.
위는 스레드를 종료하는 하나의 방법입니다. (이것도 조만간 블로그에 정리해서 올릴 예정입니다.)
위에서 volatile 변수를 사용한 이유는 stopThread의 요청을 신속하게 전달하기 위해서입니다.
만약 volatile을 사용하지 않았을 경우, stopThead 메서드와 while(runningFlag) 에서 변수에 대해 동시에 접근한다고 가정해보세요. 어떤 경우엔, stopThread를 호출했음에도 바로 정지하지 않고 한번 더 루프를 돈 후에 정지될겁니다.
이처럼 atomic한 read/write 작업에는 충분히 volatile변수는 권장될 수 있습니다.
'프로그래밍 언어 > Java' 카테고리의 다른 글
[Java] if문이 안티패턴이 되는 경우에 대해 (0) | 2020.04.09 |
---|---|
[Java] Thread를 종료하는 방법 두 가지 (0) | 2020.04.02 |
[Java][Reflection] Method 인수의 name 속성 알아내기 (0) | 2020.03.31 |
[Java] gradle 프로젝트의 컴파일 옵션 추가하기 (0) | 2020.03.30 |
[Java] 정규표현식 핵심만 알고 간단하게 사용하자 (0) | 2020.03.30 |