jnk1m
Foliage IT
jnk1m
전체 방문자
오늘
어제
  • 분류 전체보기 (209)
    • Today I Learned (34)
    • Java (47)
    • Database (15)
    • [NHN Academy] (27)
    • Spring (47)
    • HTML + CSS + JavaScript (11)
    • JSP (3)
    • Node.js (10)
    • React Native (2)
    • 기타 (8)
    • 스크랩 (5)

인기 글

최근 글

티스토리

hELLO · Designed By 정상우.
글쓰기 / 관리자
jnk1m

Foliage IT

[스레드] 스레드 동기화, 동시성 제어
Java

[스레드] 스레드 동기화, 동시성 제어

2022. 9. 12. 18:25

스레드 동기화


멀티 스레드는 하나의 객체를 공유해서 작업할 수도 있다. 이 경우, 다른 스레드에 의해 객체 내부 데이터가 쉽게 변경될 수 있기 때문에 의도했던 것과는 다른 결과가 나올 수 있다. 

 

예시)

User1Thread는 Calculator 객체의 memory 필드에 100을 먼저 저장하고 2초간 일시 정지 상태가 된다. 그동안 User2Thread가 memory 필드값을 50으로 변경한다. 2초가 지나 User1Thread가 다시 실행 상태가 되어 memory 필드의 값을 출력하면 User2Thread가 저장한 50이 나온다. 

이런 경우, Uers1Thread에 저장되니 데이터가 날아가버린다. 

 

👉 스레드가 사용 중인 객체를 다른 스레드가 변경할 수 없도록 하려면 스레드 작업이 끝날 때까지 객체에 잠금을 걸면 된다. 이를 위해 자바는 동기화(synchronized) 메소드와 블록을 제공한다. 

 


동기화 메소드 및 블록 선언


synchronized 키워드를 붙여 동기화 메소드를 선언할 수 있다.

synchronized 키워드는 인스턴스와 정적 메소드 어디든 붙일 수 있다. 

 

👇 메소드의 접근 제한자에 키워드 추가만으로도 가능하다

public synchronized void method(){
     //단 하나의 스레드만 실행하는 영역
}

 

스레드가 동기화 메소드를 실행하는 즉시 객체는 잠금이 일어나고, 메소드 실행이 끝나면 잠금이 풀린다. 

 

메소드 전체가 아닌 일부 영역을 실행할 때만 객체 잠금을 걸고 싶다면 다음과 같이 동기화 블록을 만들면 된다. 

public void method(){
   //여러 스레드가 실행할 수 있는 영역
   synchronized(공유 객체){
      //단 하나의 스레드만 실행하는 영역
   }
   //여러 스레드가 실행할 수 있는 영역
}

 

👇공유 객체로 사용할 Calculator. setMemory1()를 동기화 메소드로, setMemory2()를 동기화 블록을 포함하는 메소드로 선언했다. 따라서 setMemory1과 setMemory2는 하나의 스레드만 실행 가능한 메소드가 된다. 

public class MyPrac1{
    private int memory;
    public int getMemory(){
        return memory;
    }
    
    public synchronized void setMemory1(int memory){ //동기화 메소드
        this.memory = memory; //메모리 값 저장 
        try{
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            
        }
    }
    
    public void setMemory2(int memory){ //동기화 블록
        synchronized (this){ //클래스의 인스턴스를 줌. 이렇게 클래스의 인스턴스를 주면 해당 클래스에 있는 다른 동기화 메소드 또한 사용이 불가하다
            this.memory = memory;
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName()+":"+this.memory); //this.memory -> 메모리 값 읽기
            }
        }
    }
    
}

 

동기화 메소드와 동기화 블록에(synchronized라는 키워드가 붙은 메소드와 블록은 다 해당 됨) 객체의 인스턴스를 줄 경우, 해당 객체의 동기화 메소드를 실행할 수 없다.

동기화 메소드가 아닌 일반 메소드는 실행 가능하다. 


스레드 동시성 제어


임계 구역 (Critical Section)

병렬 컴퓨팅에서 둘 이상의 스레드가 동시에 접근해서는 안되는 공유 자원 (자료 구조 또는 장치)에 접근하는 코드의 일부를 말한다.

임계 구역은 스레드에서 작업에 필요한 최소한의 시간 동안만 유지되어야 하고, 작업이 완료된 후에는 반드시 해제되어야 한다. 

따라서 한 스레드가 임계 구역에 들어가고 작업이 진행 중이라면, 나머지 스레드들은 해당 작업이 완료될 때까지 대기해야 한다. 

스레드가 공유 자원의 상호 배제 (Mutual Exclusion)를 보장받기 위해서 임계 구역에 들어가거나 나올 떄를 위한 다양한 동시성 제어 매커니즘이 제공된다. 

 

    'Java' 카테고리의 다른 글
    • [연결 리스트]
    • [스레드] - sleep, join, wait, interrupt, notify, notifyAll, yield
    • JAVA 자바 컬렉션 연습 문제(1~7)
    • JAVA 자바 웹 개발 Day15 (Code)

    티스토리툴바