자바 최적화
11. 자바 언어 성능 향상 기법
p327
p329
크기 조정이 발생
비용이 꽤 될 것 그러므로 크기를 정확히 결정할 수 있다면 결정하고 객체를 생성하는 것이 나음
벤치마크로 알아볼 수도 있을듯?
p331
p333
자바 hashmap에서 키를 통해 값을 찾는 일련의 과정
p334
해시맵에도 용량이 있고, 보통 2배 늘리고 재배치하는 과정을 가져가는 듯.
다만 생성자에 전달되는 initialCapacity, loadFactor 두 매개 변수를 통해서 위 과정을 좀 더 효율적으로 할 수 도 있을듯
p335
레드블랙트리는 삽입/삭제/검색의 시간복잡도를 O(logN) 을 보장
p337
즉 HashSet은 내부적으로 HashMap을 사용하고 있으며, Map의 value값에는 더미 객체가 들어가는 구조라는 것
p340
p347
C와는 다르게 자바는 가비지 콜렉터가 객체에 대한 생명주기를 관리함
문제는 가비지 컬렉터가 언제 이 객체를 청소할지 모른다는 것
그래서
Obejct.finalize()
는 java9 이후 부터 deprecated됨
12. 동시 성능 기법
p361
업데이트 소설
멀티 스레딩 환경에서 발생할 수 있는 문제
A 스레드에서 업데이트 했는데, 다른(B) 스레드에는 그 업데이트 상황이 반영되지 않아 결국엔 A 스레드에서 업데이트한 것이 없어지는 현상
sychronized
블록 없이 레퍼런스를 여러 스레드에서 공유할 경우(그리고 수정한다면) 문제가 발생할 가능성이 다분더 문제는 문제가 발생할 수도 혹은 발생하지 않을 수도 있다는 점
버그 재현이 힘들 수도
p365
JMM의 메모리 모델 (고수준)
강한 메모리 모델, 전체 코어가 항상 같은 값을 바라봄
약한 메모리 모델, 코어 마다 다른 값을 바라볼 수 있고 그 시점을 제어하는 특별한 캐시 규칙이 있다.
자바에서는 강한 메모리 모델이 아닌 약한 메모리 모델을 선택
왜?
언어 자체가 아키텍쳐에 독립적인 이라는 점 (강한 메모리 모델을 지원하지 않는 하드웨어의 경우.. 이 부분을 지원하기 위해 어떻게 해야할지 난감한듯)
멀티코어 체제에 부적절하기 떄문
p 367
JMM의 기본개념
자바에서 스레드?
객체 상태 정보를 스스로 들고 다니며,
스레드가 변경한 내용은 메인 메모리에 곧장 반영괻고,
같은 데이터를 액세스하는 다른 스레드가 읽는 구조
자바의 Synchronized keyword?
JMM 기본 개념의
Synchronizes-With
와 동일즉 모니터를 장악한 스레드의 로컬 뷰가 메인 메모리와 동기화 되었다는 뜻
자바에서 동기화되지 않는 액세스는, 그러니까 이 스레드에서 변경한 부분을 언제 다른 스레드에서 읽을 수 있는지 보장하지 않음.
약한 메모리 모델이기 때문인듯
p368
그러면 Synchronized 락의 한계점?
쓰기 작업에만 Synchronized 를 적용하면, lost update 현상이 일어난다.
즉 읽기 작업을 할 때 변경된 값을 읽어 오리라는 보장이 없다.
p371
Unsafe
sum.misc.Unsafe
는 내부 구현 클래스저수준 하드웨어 명령어에 액세스할 수 있음
표준 자바 플랫폼 API가 아니다.
애플리케이션 개발자가 이 클래스를 직접 이용할 일은 거의 없다.
할 수 있는 일?
객체는 할당, 생성자는 실행하지 않음
raw memory에 액세스 하고 포인터 수준의 연산을 수행
프로세스별 하드웨어 특성 (e.g. CAS)을 이용
이를 통해
직렬화, 역직렬화
스레드 안전한 네이티브 메모리 액세스
atomic 메모리 연산
효율적인 객체/메모리 레이아웃
custom memory fence
네이티브 코드와의 상호작용
JNI에 관한 다중 운영체체 대체물..
배열 원소에 volatile하게 액세스..
p373에서
Unsafe.getUnsafe()
로 직접적으로 사용하면SecurityException
발생스프링을 사용하면
UnsafeUtils
로 접근하도록 하자https://stackoverflow.com/questions/13003871/how-do-i-get-the-instance-of-sun-misc-unsafe
java.util.concurrent 락
lock()
락을 획득하고, 락을 사용할 수 있을 때 까지 블록킹
newCondition()
락 주위에 조건을 설정해 좀 더 유연하게 락을 확용
락 내부에서 관심사 분리(읽기 혹은 쓰기)가 가능하다
tryLock()
락을 획득하려고 시도(타임아웃 설정가능)
덕분에 스레드가 락을 사용할 없는 경우에도, 처리를 진행할 수 있음.
논 블로킹 방식
unlock()
락 해제
ReentrantLock
Lock의 주요 구현체
내부적으로는 int 값이 compareAndSwap(0 함)
LockSupport
스레드에게 permit을 발급 (퍼밋 == 세마포어..?)
만약 발급할 수 있는 permit 이 없다면 스레드는 기다려야함
0, 1 binary semaphore만을 permit으로 발급함
스레드가 permit을 발급받지 못한 경우 parking 되고
유효한 permit을 발급받을 수 있다면 해당 스레드는 unparking됨
이 클래스가 Thread.suspend() -> parking, Thread.resume() -> unparking을 대체 한다
ReentrantReadWriteLock
읽기와 쓰기에서 다른 락을 사용하는 방법
즉 읽기 작업 중에는 다른 읽기 스레드는 블로킹 되지 않도록 하지만
쓰기 작업 중에는 읽기나 혹은 쓰기 스레드는 블로킹 될 것
세마포어
'최대 ~개의 객체까지만 액세스를 허용한다' 는 전제하에 정해진 수량의 permit으로 액세스를 제어하는 것
permit이 하나 뿐인 세마포어(binary semaphore)는 뮤텍스 mutex와 동등
뮤텍스는 뮤텍스가 걸린 스레드가 해제할 수 있는 반면
세마포어는 비소유 스레드도 세마포어를 해제할 수 있는 점이 다르다
p381
Happens-Before?
한 이벤트는 무조건 다른 이벤트보다 먼저 발생한다.
p384
Fork/Join
ForkJoinPool 클래스는 두가지 특성이 있음
하위 분할 태스크를 효율적으로 처리할 수 있음
작업 빼앗기 알고리즘을 구현
하위 분할 태스크?
자바 스레드보다 가벼운, 스레드와 비슷한 엔티티
ForkJoinTask 클래스가 지원하는 기능
자기 자신을 더 작은 서브 태스크를 분할하는 능력이 핵심
적은 수의 스레드가 아주 많은 태스크/서브 태스크를 담당해야하는 경우 사용
p390
자바 스트림은 데이터 소스에서 원소를 퍼 나르는 불변 데이터 시퀀스
parallelStream() 을 이용하면 병렬로 데이터를 작업 후, 그 결과를 재조합 할 수 있음
실제로 컬렉션이 작을수록 직렬 연산이 병렬 연산보다 훨씬 빠르다
그러므로 항상 패러럴스트림을 사용할 때는 성능 테스트를 해봐야한다
액터 기반 기법
actor 실행기
가번적인 상태는 일체 공유하지 않고 오직 불변 메세지를 통해서만 액터끼리 상호 교류함
이를 통해 상태 관리
전통적인 락킹 체계보다 액터가 더 좋다. 왜?
락을 쓰면 데드락..
락을 쓰면 CPU 처리율이 떨어질 수도..
Reference
http://www.yes24.com/Product/Goods/72161685
Last updated