728x90
반응형

1. thread 를 병렬로 처리하는 방법

  1. 동기화
    1. 병렬로 실행되는 스레드가 공유 리소스에 동시에 접근하려고 할 때, 무결성을 보장하기 위해 동기화 기법을 사용합니다. 동기화는 뮤텍스, 세마포어, 모니터 등의 다양한 기법이 존재
  2. 뮤텍스
    1. 상호배제를 뜻하며, 한 번의 하나의 스레드만 공유 리소스에 접근할 수 있도록 제한합니다. 뮤텍스를 사용하여 공유 리소스에 접근하는 코드 영역을 임계 영역으로 지정하면, 동시에 여러 스레드가 해당 영역을 실행하지 못하게 됩니다.
  3. 세마포어
    1. 공유 리소스에 동시에 접근할 수 있는 스레드의 수를 제한하는 동기화 기법. 세마포어는 카운터를 사용하여 특정 시점에 동시에 실행할 수 있는 스레드 수를 제한합니다.
  4. 데드락
    1. 여러 스레드가 동시에 실행될 떄, 데드락이 발생. 데드락은 스레드들이 서로가 가진 리소스를 기다리며 진행이 멈추는 상황. 데드락을 처리하러며 아래와 같은 방법을 사용해야함
      1. 리스소 순서화 : 리소스를 사용하는 순서를 정하고 스레드들이 이 순서대로 리소스를 요청할수 있도록 한다.
      2. 타임아웃 설정 : 스레드가 특정 시간동안 리소스를 얻지 못하면 요청을 취소하고 다시 시도하도록 한다.
  5. 작업 분할 및 분산
    1. 병렬로 들어온 스레드를 효율적으로 처리하기 위해, 작업을 적절한 크기의 단위로 나누고, 스레드에 할당
  6. 최적화된 스레드풀 사용
    1. 과도한 스레드 생성 및 소멸로 인한 오버헤드를 줄이기 위해 스레드 풀을 사용할 수 있습니다.

 

2. thread 동시성 문제 

  1. 락(lock) 사용
    1. 공유 리소스에 동시접근을 막기위해 락을 사용하고, 락을 사용하면 한 번에 하나의 스레드만 해당 리소스에 접근이 가능, java 에서는 synchronized 키워드를 사용하거나 reentrantLock을 사용
  2. 원자적(Atomic) 연산
    1. 원자적 연산은 여러 스레드에서 동시에 실행되더라도 중간 결과를 공유하지 않으므로 동시성 문제가 발생하지 않습니다. 자바에서는 AtomicInteger 와 같은 원자적 클래스를 사용할 수 있습니다.
  3. 뮤텍스
    1. 공유리소스에 접근하는 코드영역을 임계 영역으로 지정하여 동시에 여러 스레드가 해당 영역을 실행하지 못하도록 합니다.
  4. 세마포어
    1. 동시에 접근할 수 있는 스레드 수를 제한하여 동시성 문제를 해결하는 기법
  5. 모니터
    1. 객체 내부에서 뮤텍스와 조건 변수를 사용하여 동시성 문제를 해결하는 기법
    import java.util.LinkedList;
    import java.util.Queue;
    
    public class ProducerConsumerMonitor {
        private final Queue<Integer> buffer;
        private final int maxSize;
    
        public ProducerConsumerMonitor(int maxSize) {
            this.maxSize = maxSize;
            this.buffer = new LinkedList<>();
        }
    
        public synchronized void produce(int item) throws InterruptedException {
            while (buffer.size() == maxSize) {
                wait();
            }
    
            buffer.add(item);
            System.out.println("Produced: " + item);
            notifyAll();
        }
    
        public synchronized int consume() throws InterruptedException {
            while (buffer.isEmpty()) {
                wait();
            }
    
            int item = buffer.remove();
            System.out.println("Consumed: " + item);
            notifyAll();
            return item;
        }
    
        public static void main(String[] args) {
            ProducerConsumerMonitor monitor = new ProducerConsumerMonitor(5);
    
            Thread producer = new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    try {
                        monitor.produce(i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
    
            Thread consumer = new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    try {
                        monitor.consume();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
    
            producer.start();
            consumer.start();
        }
    }
    
  6. 읽기-쓰기락 사용
    1. 읽기-쓰기 락은 여러 스레드가 동시에 읽기 작업을 수행하면서, 쓰기 작업은 독점적으로 수행하도록 제한하는 동기화 기법
728x90
반응형

+ Recent posts