자바 멀티스레드 공유변수 문제가 있습니다.

조회수 3674회

제가 자바로 컨솔게임을 만들면서 적군의 행동을 멀티스레드로 쓰고 있습니다.

스레드를 클래스로 따로 만들어 메인에서 start()시켜줍니다.

스레드안의 구조는 적군의 체력(static변수)이 0이하로 될 때까지 돌도록 반복문으로 돌렸고요.

하지만 멀티스레드이다보니까 적군의 체력이 0이하로 되어도 계속 돌더라고요.

우선 스레드 앞뒤로 출력값을 보아 제대로 적군의 체력이 0이하가 되는 지 확인을 했고, 이 점은 이상이 없었습니다.

그리고 싱글스레드로만 돌렸을 때는 동작이 멈추는 것을 확인했습니다.

그래서 찾아보니 스레드를 공유하여 접근한다면 run()메서드에 싱크로나이즈를 붙여주라고 해서

붙여줬는데도 하나만 스레드가 중단되고, 하나는 계속 진행이 됩니다.

이럴 땐 어떻게 해야할까요?

싱크로나이즈가 답이 아닌가요?

방법만 알려주시면 제가 혼자 해보고 싶어서 입코딩으로만 올렸습니다.

읽어주셔서 감사합니다.

1 답변

  • 공유 변수의 값을 확인하거나 변경하는 코드를 Critical Section 으로 변경해야 합니다.

    Critical Section이란 간단히 말해서, 제한적으로 접근을 허용할 수 있는 구간을 말합니다. 통상 하나의 스레드만 접근할 수 있게할 때 사용합니다.

    public class Shared {
        private static Shared instance = new Shared(); // 싱글톤 패턴의 인스턴스
    
        public static Shared getInstance() { return instance; }
    
        private int count;
    
        private Shared() {} // 싱글톤으로 하기 위해서 private 생성자로 함.
    
        public int getCount() { return count; }
        public void setCount(int count) { this.count = count; }
        public int increment() { return ++count; }
        public int decrement() { return --count; }
        public int increment(int x) { return (count+=x); }
        public int decrement(int x) { return (count-=x); }
    }
    

    공유의 예를 간단히 하기 위해서 싱글톤 패턴의 클래스를 예로 들었습니다. 위 Shared의 인스턴스( Shared.getInstance())를 여러개의 스레드가 공유할 경우에 count의 값의 변경이 스레드간에 동기화되지 않을 수 있습니다.

    간단히 해결하는 방법은 다음과 같이 synchronized를 추가하는 방법이 있습니다.

    public synchronized int getCount() ...;
    public synchronized void setCount(int count) ...;
    

    다른 방법은 java.util.concurrent 패키지에 있는 ReentrantLock 을 사용하시면 됩니다.

    class X {
       private final ReentrantLock lock = new ReentrantLock();
       // 락 설정. -- synchronized 키워드를 대체할 예정.
    
       public void m() {
         lock.lock();  // Critical 섹션의 시작
         try {
           // Critical 섹션 코드
         } finally {
           lock.unlock(); // Critical 섹션 해제
         }
       }
     }
    
    

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)