맥북 에어 M2 두달 간의 수리 이야기 ( feat. 위장 침수 )
·
5️⃣ 일상이야기
0. 맥북 구매 (2023년 7월 22일)정확한 기록을 위해, 구매한 Apple 맥북 에어 13 M2의 사양을 알려드리겠습니다.- 구매일자 : 2023년 7월 22일- 구매처 : 쿠팡 (애플 공식 브랜드관)- 운영체제: MAC OS- 모델명/품번: Z15T0001K- CPU : M2 8코어- GPU : 16코어- RAM : 16G- 저장용량 : 512G- 애플케어 : 가입 안함 1. 사건의 발단 (2024년 10월 26일)맥북을 구매 후 약 1년 3개월 간 사용하면서, 무거운 프로그램을 돌린적도 없고 오염이 될 만한 행위 자체도 하지 않았다. (항상 파우치에 넣고 다님). 그러던 중, 어느 날 맥북을 사용하다가 (넷플릭스로 미생을 보고 있었음) 정말 갑자기 화면이 치지직 거린 뒤 1초 후에 노트북이 갑자..
[아이템84] 프로그램의 동작을 스레드 스케줄러에 기대지 말라
·
1️⃣ 백앤드/이펙티브 자바
1. 스레드 스케줄러여러 스레드가 실행 중이면, 운영체제의 스레드 스케줄러가 어떤 스레드를 얼마나 오래 실행할지 정한다. 이 때, 운영체제마다 스케줄링 정책이 다를 수가 있는데 잘 작성된 프로그램이라면 이 정책에 좌지우지 되면 안된다. 즉, 프로그램의 동작을 스레드 스케줄러에 기대지 말고 독립적으로 가져가야 한다는 말이다.실행 가능한 스레드의 평균적인 수를 프로세서 수보다 지나치게 많아지지 않도록 하자.실행 준비가 된 스레드들은 맡은 작업을 완료할 때까지 계속 실행되도록 만들자.스레드는 절대 바쁜 대기 상태로 두지 말자. 다시 말해 공유 객체의 상태가 바뀔 때까지 쉬지 않고 검사해서는 안된다는 것이다.피해야 할 예로, CountDownLatch 를 바쁜 대기 버전으로 만든 구현을 살펴보자.public c..
[아이템83] 지연 초기화는 신중히 사용하라
·
1️⃣ 백앤드/이펙티브 자바
1. 지연 초기화지연 초기화는 필드의 초기화 시점을 그 값이 처음 필요할 때까지 늦추는 기법이다. 값이 쓰이지 않으면 초기화도 일어나지 않게 된다. 주로 최적화 용도로 쓰이지만, 클래스와 인스턴스 초기화 때 발생하는 위험한 순환 문제를 해결하는 효과도 있다.지연 초기화는 필요할 때까지 하지 말자.클래스의 인스턴스 생성 초기 비용은 훨씬 줄지만, 필드에 접근하는 비용은 커진다. 오히려 성능이 느려질 수 있다. 그래서 그 필드를 사용하는 인스턴스의 비율이 낮으며 그 필드를 초기화하는 비용이 컸을 때 지연 초기화가 제 역할을 한다. 이를 위해 지연 초기화 적용 전후의 성능을 측정해봐야 한다.2. 멀티쓰레드 환경에서의 지연 초기화멀티쓰레드 환경에서 지연 초기화를 하기란 까다롭다. 지연 초기화하는 필드를 둘 이상..
[아이템82] 스레드 안전성 수준을 문서화해라
·
1️⃣ 백앤드/이펙티브 자바
1. 스레드 안전성 수준한 메서드를 여러 쓰레드가 동시에 호출했을 때, 그 메서드가 어떻게 동작하는지는 해당 클래스를 사용하는 클라이언트 입장에선 굉장히 중요하다. API 문서에 아무런 언급이 없으면 그 클래스 사용자는 혼자서 나름의 가정을 해야하기 때문이다.멀티쓰레드 환경에서 API 를 안전하게 사용하기 위해선, 클래스가 지원하는 쓰레드 안전성 수준을 정확히 명시하자.아래는 쓰레드 안전성이 높은 순서이다. 문서화할 때 참고하도록 하자.1. 불변 : 이 클래스의 인스턴스는 상수와 같아서, 외부 동기화가 필요 없다. (ex. String, Long, BigInteger)2. 무조건적 쓰레드 안전 : 이 클래스의 인스턴스는 수정될 수 있으나, 내부 동기화를 통해 외부 동기화 없이 사용해도 안전하다.(ex. ..
[아이템81] wait 와 notify 보다는 동시성 유틸리티를 애용해라
·
1️⃣ 백앤드/이펙티브 자바
1. wait 과 notifywait 과 notify 는 멀티쓰레드 환경에서 동기화된 작업을 위해 사용된다. 이 메서드들은 특정 조건이 충족될 때까지 스레드를 대기 상태로 만들거나, 대기 중인 스레드를 깨우는 데 사용된다.wait() 메서드는 현재 쓰레드를 대기 상태로 만들며, 객체의 모니터 락을 걸다가 다른 쓰레드가 notify() 메서드로 깨우면 락이 해제된다.notify() 메서드는 대기 상태에 있는 쓰레드를 깨우는 역할을 한다.class SharedResource { synchronized void waitMethod() { try { System.out.println("Thread is waiting..."); wait(); // 현재 스..
[아이템80] 스레드보다는 실행자, 태스크, 스트림을 애용하라
·
1️⃣ 백앤드/이펙티브 자바
1. java.util.concurrent 패키지이 패키지는 실행자 프레임워크 (Executor Framework) 라고 하는, 인터페이스 기반의 태스크 실행 기능을 담고 있다. 클라이언트 요청에 의해 쌓인 작업 큐를 생성할 수 있는 코드를 단 한줄로 작성할 수 있다.// 작업 큐를 생성하다. ExcutorService exec = Executors.newSingleThreadExcutor();그리고, 이 실행자에 실행할 태스크를 넘기는 방법도 단 한줄로 작성할 수 있다.// 다음은 이 Excutor에 실행할 태스크(task; 작업)를 넘기는 방법이다.exec.execute(runnable);그리고, 실행자를 종료시킬 수 있다.exec.shutdown();실행자 서비스의 기능은 이 외에도 많은데, 아래..
[아이템79] 과도한 동기화는 피하라
·
1️⃣ 백앤드/이펙티브 자바
1. 과도한 동기화과도한 동기화는 성능을 떨어뜨리고, 교착상태에 빠뜨리고, 심지어 예측할 수 없는 동작을 낳기도 한다.1-1. 정확성을 떨어뜨린다.synchronized 를 활용한 동기화 메서드, 동기화 블록을 아이템 78에서 확인했다. 이 안에서는 절대로 제어를 클라이언트에게 양도하면 안된다. 알지 못하고 검증되지 않은 메서드는 무슨 일을 할지 몰라 통제할 수 없기 때문이다. 예외를 일으키기도 하고, 데이터를 훼손시킬 수도 있다. 아래 집합을 감싼 ObservableSet 래퍼 클래스를 확인해보자.public class ObservableSet extends ForwardingSet { public ObservableSet(Set set) { super(set); } pri..
[아이템78] 공유 중인 가변 데이터는 동기화해 사용하라
·
1️⃣ 백앤드/이펙티브 자바
1. 동기화synchronized 키워드를 통해 메서드나 블록에 한 쓰레드씩 접근할 수 있도록 할 수 있다. 즉, 한 쓰레드가 변경중인 상태가 일관되지 않은 순간의 객체를 다른 쓰레드가 접근하지 못하는 용도로 사용한다.일종의 락을 걸고, 객체의 상태를 변화시킨다. 동기화를 제대로 사용한다면 어떤 메서드도 이 객체의 상태가 일관되지 않은 순간을 볼 수 없을 것이다. 이를 동기화라고 한다. 그리고, 동기화 된 메서드나 블록에 접근해 수행한 쓰레드가 만든 변화는 다른 쓰레드에서 확인이 가능하다.long, double 외 변수를 읽고 쓰는 동작은 원자적이다. 여러 쓰레드가 같은 변수를 동기화 없이 수정해도, 항상 어떤 쓰레드가 정상적으로 저장한 값을 온전히 읽어온다. 그렇다고 이 경우에 동기화를 배척해서는 안된..
[아이템77] 예외를 무시하지 말라
·
1️⃣ 백앤드/이펙티브 자바
1. 예외를 무시하지 마!API 설계자가 메서드 선언에 예외를 명시하는 이유는, 그 메서드를 사용할 때 적절한 조치를 취해달라고 하는 것이다. 절대 무시하지 말자. try 문으로 감싼 후 catch 블록을 비워놔선 절대 안된다. 너무 당연한 이야기다.// catch 블록을 비워두면 예외가 무시된다. 아주 의심스러운 코드다!try { ...} catch (SomeException e) {}위 처럼 catch 블록을 비워두면 예외가 존재할 이유가 없다. 2. 예외를 무시해도 돼!예를 들어 FileInputStream 을 닫을 때가 그렇다. 입력 전용 스트림이므로, 파일의 상태를 변경하지 않았으니 복구할 것도 없고, 스트림을 닫는다는 건 필요한 정보는 이미 다 읽었다는 뜻이니 예외를 처리할 이유가 없다. 혹시..
[아이템76] 가능한 한 실패 원자적으로 만들라
·
1️⃣ 백앤드/이펙티브 자바
1. 실패 원자적DB 공부를 하다보면 ACID 원칙 중 첫번째로 원자성을 보장하라. 라는 말은 많이 들어봤을 것이다. 한마디로 all or nothing 으로, 중간에 실패하면 다시 돌아와야 한다는 것이다.예외에서도 마찬가지다. 메서드를 실행하다가 실패했을 때, 내부 객체는 메서드 호출 전 상태를 유지해야 한다.1-1. 메서드를 실패 원자적으로 만드는 방법1-1-1. 불변 객체 사용애초에 불변 객체로 설계하는 방법이다. 불변 객체는 태생적으로 실패 원자적이다. 메서드 내에서 실패하더라도 태생적으로 실패 원자적인 불변 객체가 불안정한 상태에 빠질 일이 결코 없다. 불변 객체는 생성 시점부터 고정되어 변하지 않는다.1-1-2. 가변 객체 사용하더라도..가변 객체의 경우에 실패 원자적으로 만드는 방법은 작업 ..