본문 바로가기
[Java Concurrency] 구성 단위 #1 [Java Concurrency] 구성 단위 #1 5.1. 동기화된 컬렉션 클래스 - 동기화되어 있는 컬렉션 클래스의 대표 주자는 Vector 와 Hashtable 이다. - JDK 1.2 부터는 Collections.synchronizedXxx 메소드를 사용해 이와 비슷하게 동기화되어 있는 몇 가지 클래스를 만들어 사용할 수 있게 됐다. 이와 같은 클래스는 모두 public 으로 선언된 모든 메소드를 클래스 내부에 캡슐화해 내부의 값을 한 번에 한 스레드만 사용할 수 있도록 제어하면서 스레드 안전성을 확보하고 있다. - 동기화된 컬렉션 클래스는 스레드 안전성을 확보하고 있기는 하다. 하지만 여러 개의 연산을 묶어 하나의 단일 연산처럼 활용해야 할 필요성이 항상 발생한다. - 동기화된 컬렉션 클래스는 대.. 2017. 4. 20.
[Java Concurrency] 객체공유 [Java Concurrency] 객체공유 3.1. 가시성 - 일반적으로 특정 변수의 값을 가져갈 때 다른 스레드가 작성한 값을 가져갈 수 있다는 보장도 없고, 심지어는 값을 읽지 못 할 수도 있다. 메모리상의 공유된 변수를 여러 스레드에서 서로 사용할 수 있게 하려면 반드시 동기화 기능을 구현해야 한다. - 재배치(reordering) 현상을 조심해야 한다. 재배치 현상은 특정 메소드의 소스코드가 100% 코딩된 순서로 동작한다는 점을 보장할 수 없다는 점에 기인하는 문제이다. 단일 스레드로 동작할 때는 차이점을 전혀 알아챌 수 없지만 여러 스레드가 동시에 동작하는 경우에는 확연하게 나타날 수 있다. - 동기화 기능을 지정하지 않으면 컴파일러나 프로세서, JVM 등이 프로그램 코드가 실행되는 순서를 임.. 2017. 4. 17.
[Effective Java] 독자적인 직렬화 형태의 사용을 고려하자 [Effective Java] 독자적인 직렬화 형태의 사용을 고려하자 - 클래스를 설계할 때 클래스가 Serializable 을 구현하면서 기본 직렬화 형태를 사용한다면, 나중에 함부로 버릴 수 없고, 그 직렬화 형태를 계속 유지해야 할 가능성이 높다. - 적합 여부를 우선적으로 고려해보고 기본 직렬화 형태를 수용하자. 기본 직렬화 형태는 유연성, 성능, 정확성의 관점에서 타당하다는 결정이 섰을 때 사용해야 한다. 일반적으로 말하면, 우리가 독자적인 직렬화 형태를 설계한다고 할 때 하게될 인코딩과 대부분 같은 경우에만 기본 직렬화 형태를 사용해야 한다. - 이상적인 객체 직렬화 형태는 그 객체가 표현하는 논리적 데이터만 포함한 것이다. - 기본 직렬화 형태는 객체의 물리적 표현이 논리적인 내용과 동일할 .. 2017. 3. 23.
[Effective Java] 스레드 그룹을 사용하지 말자. [Effective Java] 스레드 그룹을 사용하지 말자. - 스레드, 락, 모니터에 더하여 스레드 시스템에서 제공하는 기본 추상체가 스레드 그룹(thread group) 이다. 스레드 그룹은 원래 보안을 목적으로 애플릿을 격리시키는 메커니즘으로 구상되었다. 그러나 실제로는 그런 기대를 충족시키지 못해 자바 보안 모델의 표준에서 언급되지 않을 정도로 쇠약하다. - 스레드 그룹은 기능이 별로 없다. 단지 Thread 클래스의 기본 메소드들을 여러 스레드가 포함된 그룹에 일괄로 한번에 적용할 수 있게 해준다. 그런 기본 메소드들 중 상당 수는 이미 사용금지 되었으며 남은 메소드들은 사용되는 경우가 드물다. - ThreadGroup 클래스의 API 메소드는 스레드 안전 관점에서도 빈약하다. 하나의 스레드 그.. 2017. 3. 20.
[Effective Java] 스레드 스케쥴러에 의존하지 말자 [Effective Java] 스레드 스케쥴러에 의존하지 말자 - 많은 스레드가 runnable 상태일 때는 어떤 스레드를 실행시킬 것인지, 그리고 얼마 동안 실행시킬 것인지를 스레드 스케쥴러가 결정한다. 운영체제에서는 공정하게 그런 결정을 내리려고 하겠지만, 그 정책은 서로 다를 수 있다. 따라서 잘 작성한 프로그램은 그런 정책의 상세한 내용에 매달려서는 안 된다. 정확성이나 성능을 스레드 스케줄러에 의존하는 프로그램이라면 그 어떤 것도 이식성이 없어질 가능성이 크다. - 강력하고, 응답성이 좋고, 이식성이 있는 프로그램을 작성하는 가장 좋은 방법은, runnable 상태의 평균 스레드 개수가 프로세서의 개수보다 그리 크지 않게 하는 것이다. 이렇게 하면 스레드 스케줄러는 선택의 여지 없이 runnab.. 2017. 3. 17.
[Effective Java] wait 와 notify 대신 동시성 유틸리티를 사용하자. [Effective Java] wait 와 notify 대신 동시성 유틸리티를 사용하자. - wait 와 notify 를 사용할 이유가 거의 없다. 자바 1.5 배포판 기준으로 고수준 동시성 유틸리티를 제공한다. wait와 notify 를 올바르게 사용하기 어렵다면, 그 대신에 고수준 동시성 유틸리티를 사용해야 한다. - java.util.concurrent 패키지의 고수준 유틸리티는 세 부류로 나누어진다. 실행자 프레임워크(executor framework) 동시적 컬렉션 및 동기자(synchronizer) - 동시적 컬렉션은 List, Queue, Map 과 같은 표준 컬렉션 인터페이스를 고성능의 동시적 구현체로 제공한다. 높은 동시성을 제공하기 위해 이 구현체들은 내부적으로 자기 나름의 동기화를 한.. 2017. 3. 13.
[Effective Java] 스레드 그룹보다는 실행자와 작업을 사용하자. [Effective Java] 스레드 그룹보다는 실행자와 작업을 사용하자. - 자바 1.5 배포판 이후에 java.util.concurrent 패키지가 추가되었다. 여기에는 실행자 프레임워크(Executor Framework) 가 포함되어 있다. 이 녀석을 사용하면 Work queue 를 쉽게 관리할 수 있다. ExecutorService executor = Executors.newSingleThreadExecutor();executor.execute(runnable);executor.shutdown(); // 추가된 task 들의 실행은 보장한다. shutdownNow() 도 있다. 위와 같은 간단한 코드로 쉽게 queue 를 만들어 실행시킬 수 있고, shutdown 시킬 수 있다. - Executo.. 2017. 3. 10.
[Effective Java] 공유하는 가변 데이터에 접근 시 동기화하자. [Effective Java] 공유하는 가변 데이터에 접근 시 동기화하자. - 동기화를 하지 않으면, 하나의 스레드에서 변경한 내용을 다른 스레드에서 못 볼 수 있다. 동기화는 불안정 상태의 객체를 스레드가 볼 수 없도록 하는 것은 물론, 동기화된 메소드나 블록에 진입하는 각 스레드가 앞에서의 모든 변경(같은 락으로 보호되었던)이 반영된 결과를 볼 수 있게 해준다. - 자바 언어 명세에서는 long 이나 double 타입이 아닌 변수의 값을 읽거나 쓸 때는 원자성을 보장한다. long 이나 double 타입이 아닌 변수의 값을 읽으면 어떤 스레드가 그 변수에 저장했던 값을 반환 받을 수 있다는 것. 실제로 동기화하지 않고 여러 스레드가 그 변수를 동시에 수정해도 그때그때 수정된 값이 반영된다. 스레드가 .. 2017. 3. 7.
[Effective Java] 가변성을 최소화 하자. [Effective Java] 가변성을 최소화 하자. -불변 클래스는 자신의 인스턴스가 갖는 값을 변경할 수 없는 클래스. - 불변 클래스는, 가변 클래스에 비해 설계와 구현 및 사용이 더 쉽다. 에러 발생이 적으며 보안이나 사용 측면에서 더 안전하다. - 불변 클래스를 만들 때는 다음 다섯 가지 규칙을 따르자. 1. 객체의 상태를 변경하는 그 어떤 메소드도 제공하지 않는다. 2. 상속을 할 수 없도록 하자. ( class 에 final 을 주어 막을 수 있다. ) 3. 모든 필드를 final 로 지정한다. 4. 모든 필드를 private 으로 지정한다. 5. 가변 컴포넌트의 직접적인 외부 접근을 막자. 생성자와 접근자 메소드 및 readObject 메소드에서 해당 객체의 방어 복사본을 만들어 사용하도록.. 2016. 10. 24.
반응형