스레드 직접 사용 시 문제점실무에서 스레드를 직접 생성해서 사용할 때의 문제점스레드 생성 비용으로 인한 성능 문제각 스레드의 호출 스택을 가지고 있어야 하기에 메모리 할당 문제스레드 생성 작업은 운영체제 커널 수준에서 이루어져 시스템 콜을 통해 처리되는데 이로 인해 CPU와 메모리 리소스를 소모운영체제의 스케줄러가 스레드 관리, 실행 순서 조정을 위해 오버헤드 발생해결 방법 : 스레드는 처음 생성할 때만 비용이 들기에 생성된 스레드를 재사용하는 방법스레드 관리 문제CPU, 메모리 자원은 한정되어 있기에 스레드는 무한하게 만들 수 없다.시스템이 버틸 수 있는 최대 스레드 수까지만 생성할 수 있게 관리해야 한다.Runnable 인터페이스의 불편함run() 메소드는 반환 값을 가지지 않기에 스레드의 실행 결과..
프록시 (Proxy)Proxy : 대리자, 대신 처리해주는 역할을 수행한다.프록시는 원본과 똑같이 생겼고 원본과 같은 인터페이스를 구현함으로 호출하는 메소드도 똑같다.프록시는 내부에 원본을 가지고 있으며 프록시가 필요한 일의 일부를 처리하고 그 다음 원본을 호출하는 구조를 만들 수 있다. //인터페이스, 추상화 역할public interface SimpleList { void add(Object e);}//SimpleList 구현체public class BasicList implements SimpleList { void add(Object e) {...}}//SimpleList 구현체이자 프록시public class SyncProxyList implements SimpleList { private Si..
원자적 연산원자적 연산 : 해당 연산이 더 이상 나눌 수 없는 단위로 수행된다는 것을 의미한다.중단되지 않고 다른 연산과 간섭 없이 완전히 실행되거나 전혀 실행되지 않는 성질을 가진다.멀티스레드 상황에서 다른 스레드의 간섭 없이 안전하게 처리되는 연산이라는 뜻 int i = 1; //원자적 연산i = i + 1; //원자적 연산이 아니다.i = 1;은 더 이상 쪼갤 수 없는 원자적 연산이다.i = i + 1; 은 순서로 나눠 실행되기 때문에 원자적 연산이 아니다.오른쪽 i의 값을 읽는다.읽은 값에 1을 더한다.계산된 값을 왼쪽 i에 대입한다.원자적 연산은 멀티스레드 상황에서 아무런 문제가 발생하지 않지만 원자적 연산이 아닌 경우에는 synchronized 블록이나 Lock을 사용해서 안전한 임계 영역을 ..
생산자 소비자 문제 (Producer-Consumer Problem)생산자 소비자 문제는 멀티 스레드 프로그래밍에서 자주 등장하는 동시성 문제로 동시에 데이터를 생산하고 소비하는 상황을 다룬다.생산자 스레드와 소비자 스레드가 특정 자원을 함께 생산하고 소비하면서 발생하는 문제이다.중간 버퍼의 크기가 한정되어 있기에 발생하므로 한정된 버퍼 문제(Bounded-Buffer Problem)이라고도 불린다. 기본 개념생산자: 데이터를 생산하는 역할로 파일에서 데이터를 읽어오거나 네트워크에서 데이터를 받아오는 스레드가 생산자 역할을 할 수 있다.소비자: 생성된 데이터를 사용하는 역할로 데이터를 처리하거나 저장하는 스레드가 소비자 역할을 할 수 있다.버퍼: 생산자가 생성한 데이터를 일시적으로 저장하는 공간으로 한정..
concurrent 패키지synchronized의 단점을 보완하며 더 유연하고 세밀한 제어가 가능하도록 concurrent 패키지가 추가되었다.LockSupportconcurrent 패키지 중 가장 기본이 되는 LockSupport가 있다.LockSupport의 대표적인 기능park() : 스레드를 WAITING 상태로 변경한다.스레드가 WAITING 상태이기에 interrupt()로 중간에 깨울 수 있다.parkNanos(nanos) : 스레드를 나노초 동안만 TIMED_WAITING 상태로 변경한다.지정 시간이 지나면 RUNNABLE 상태로 변경된다.1초 = 1000밀리초(ms), 1밀리초(ms) = 1,000,000나노초(ns)unpark(thread) : WAITING 상태의 대상 스레드를 RUN..
동기화동기화 : 여러 스레드가 동시에 접근할 수 있는 자원에 대해 일관성 있고 안전한 접근을 보장하기 위한 메커니즘이다.멀티스레드를 사용할 때 가장 주의할 점은 같은 자원(리소스)에 여러 스레드가 동시에 접근할 때 발생하는 동시성 문제이다.ex) 은행에서 출금을 동시에 하는 경우 잔액은 공유 자원이 되는데 이때 동시성 문제가 발생하면 잔액 보다 더 많은 돈을 출금하는 경우가 생겨버린다.공유 자원 : 여러 스레드가 접근하는 자원대표적인 공유 자원은 인스턴스의 필드(멤버 변수)이다.멀티스레드를 사용할 때 공유 자원에 대한 접근을 동기화해서 동시성 문제가 발생하지 않도록 방지하는 것이 중요하다.임계 영역 (critical section)임계 영역 : 여러 스레드가 동시에 접근하면 데이터 불일치나 예상치 못한 ..
메모리 가시성메모리 가시성 : 멀티스레드 환경에서 한 스레드가 변경한 값이 다른 스레드에서 언제 보이는지에 대한 문제를 의미한다. public class VolatileFlagMain { public static void main(String[] args) { MyTask task = new MyTask(); Thread t = new Thread(task, "work"); t.start(); sleep(1000); task.runFlag = false; log("runFlag = " + task.runFlag); } static class MyTask implements Runnable { boole..
스레드스레드 기본 정보스레드 이름은 중복될 수 있지만 스레드 ID는 자바에서 직접 생성해주고 중복되지 않는다.운영체제마다 다르지만 스레드의 우선순위가 높을수록 더 자주 실행된다.1 ~ 10 까지 지정할 수 있으며 기본 값은 5로 지정된다.Thread 클래스의 toString()은 스레드 ID, 이름, 우선순위, 스레드 그룹을 포함해서 반환한다.스레드 이름은 주로 로깅을 목적으로 지정한다.이름을 지정해주지 않으면 자동으로 생성해서 지어준다.ex) Thread-1, Thread-A스레드는 그룹화해서 관리할 수 있으며 부모 스레드와 동일한 스레드 그룹에 속하게 된다.그룹으로 특정 작업(일괄 종료, 우선순위 설정 등)을 수행할 수 있다.스레드 그룹 기능은 직접적으로 잘 사용되지 않는 기능이다.부모 스레드 : 새..
자바 메모리 구조메소드 영역 : 프로그램을 실행하는데 필요한 공통 데이터를 관리하는 영역으로 프로그램의 모든 영역에서 공유한다.클래스 정보 - 클래스 실행 코드, 필드, 메소드, 생성자 코드 등...static 영역 - static 변수를 보관한다.런타임 상수 풀 - 프로그램을 실행하는데 필요한 공통 리터럴 상수를 보관한다.스택 영역 : 자바 실행 시(각 스레드 별로) 하나의 실행 스택이 생성되며 각 스택 프레임은 지역 변수, 중간 연산 결과, 메소드 호출 정보 정보 등을 포함한다.스택 프레임 - 스택 영역 안에 쌓이는 네모 박스가 하나의 스택 프레임으로 메소드 호출 시마다 하나의 스택 프레임이 쌓이고 메소드 종료 시 해당 스택 프레임이 제거된다.스레드 수 만큼 스택 영역이 생성된다.힙 영역 : 객체와 ..
멀티 태스킹 / 멀티 프로세싱프로그램 실행 - 프로그램을 구성하는 코드를 순서대로 CPU에서 연산(실행)하는 일 멀티태스킹(Multi Tasking) : 하나의 컴퓨터 시스템이 (하나의 CPU 코어로) 동시에 여러 작업을 수행하는 능력시분할(Time Sharing, 시간 공유) 기법 : 여러 프로그램의 실행 시간을 분할해서 동시에 실행되는 것처럼 하는 기법시분할 기법을 사용하면 CPU 코어가 하나만 있어도 여러 프로그램이 동시에 실행되는 것처럼 느낄 수 있다.운영 체제마다 다르지만 대략 0.01초 단위로 돌아가면서 실행한다.(CPU는 초당 수십억 번 이상의 연산을 수행) 스케줄링(Scheduling) : CPU에 어떤 프로그램이 얼마만큼 실행되는지 운영체제가 결정하는 것시간만으로 작업을 분할하지 않고 다..