diff --git "a/11\354\236\245/78_\352\263\265\354\234\240_\354\244\221\354\235\270_\352\260\200\353\263\200_\353\215\260\354\235\264\355\204\260\353\212\224_\353\217\231\352\270\260\355\231\224\355\225\264_\354\202\254\354\232\251\355\225\230\353\235\274_\352\271\200\353\263\264\353\260\260.md" "b/11\354\236\245/78_\352\263\265\354\234\240_\354\244\221\354\235\270_\352\260\200\353\263\200_\353\215\260\354\235\264\355\204\260\353\212\224_\353\217\231\352\270\260\355\231\224\355\225\264_\354\202\254\354\232\251\355\225\230\353\235\274_\352\271\200\353\263\264\353\260\260.md"
new file mode 100644
index 0000000..7d3010f
--- /dev/null
+++ "b/11\354\236\245/78_\352\263\265\354\234\240_\354\244\221\354\235\270_\352\260\200\353\263\200_\353\215\260\354\235\264\355\204\260\353\212\224_\353\217\231\352\270\260\355\231\224\355\225\264_\354\202\254\354\232\251\355\225\230\353\235\274_\352\271\200\353\263\264\353\260\260.md"
@@ -0,0 +1,203 @@
+# 아이템 78. 공유 중인 가변 데이터는 동기화해 사용하라
+
+# 결론
+
+**여러 스레드가 가변 데이터를 공유한다면 그 데이터를 읽고 쓰는 동작은 반드시 동기화해야 한다.**
+
+- 스레드간 공유되는 가변 데이터의 동기화를 하지 않거나 실패하면, 프로그램이 응답 불가 상태에 빠지거나 안전 실패(Safety failure)에 빠질 수 있다.
+- 이러한 문제의 디버깅 난이도는 가장 어려운 축에 속한다.
+
+베타적 실행은 필요없고, 스레드끼리의 통신만 필요하다면 `volatile` 한정자만으로도 동기화 할 수 있다.
+
+- 하지만 올바르게 사용하기가 어렵다!
+
+---
+
+
+
+# 동기화
+
+Mutli-thread를 잘 사용하면 좋은 성능을 낼 수 있다. 하지만 스레드간 동기화는 반드시 고려해야한다. 만약 동기화를 고려하지 않는다면, **서로 공유하는 데이터에 대해 안정성과 신뢰성을 보장할 수 없고, 이는 곧 프로그램의 일관성 및 안정성을 보장할 수 없다는 것**이다.
+
+동기화에는 2가지 중요한 기능이 있다.
+
+**1. 배타적 실행(Exclusion): 한 스레드가 객체를 변경하는 중이라, 상태가 일관되지 않은 순간의 객체를 다른 스레드가 보지 못하게 막는 것**
+- 한 객체가 일관된 상태를 가지고 생성되고, 이 객체에 접근하는 메서드는 그 객체에 락을 건다. 락을 건 메서드는 객체의 상태를 확인하고 필요하면 수정한다.
+- → 일관된 상태에서 다른 일관된 상태로 변화시킴으로서 이 객체의 상태가 일관되지 않은 순간을 볼 수 없게 한다.
+
+**2. 스레드간의 통신(Communication): 한 스레드가 만든 변화를 다른 스레드에서 볼 수 있게 하는 것**
+
+- 동기화된 메서드나 블록에 들어간 스레드가 같은 락의 보호하에 수행된 모든 수정의 **최종결과**를 보게 해준다.
+
+---
+
+# Java synchronized
+
+Java에서는 `synchronized` 키워드를 통해 메서드나 블록을 한번에 한 스레드씩 수행하도록 보장함으로써 동기화를 지원하고 있다.
+
+---
+
+언어 명세상 long, double 외의 변수를 읽고 쓰는 동작은 원자적(Atomic)이다.
+
+- 여러 스레드가 같은 변수를 **동기화 없이 수정하는 중**이라도, 항상 어떤 스레드가 **정상적으로 저장한 값을 온전히 읽어옴을 보장**한다는 것
+
+
+
+"엥? 그럼 성능 높이려면 원자적인 데이터 읽고 쓸 땐 동기화 안해야겠다!"
+
+- 자바는 **한 스레드가 저장한 값이 다른 스레드에게 '보이는가'는 보장하지 않는다.**
+- 즉, 이러한 생각은 위험한 생각!
+
+# 예제
+
+Thread를 작동 중 멈추고 싶다.
+
+- `Thread.stop` ? : 사용해서는 안된다. 안전하지 않아 사용이 금지되었다.
+ - `Thread.stop(Throwable obj)` 는 Java 11에서 제거되었다. 신기한건 96년도에 만들어졌고 98년도에 자제 API로 지정되었는데 Java11이 되어서 삭제되었다. 즉, 20년이 더 걸렸다.
+ - → 공개 API는 신중히 설계해야한다.... (Thread.stop() 아직까지도 남아있다고 함)
+
+
+
+그럼, 올바르게 삭제하기 위해선 어떻게 해야 하는가?
+
+- `boolean` 필드를 두고 false로 초기화한 후 반복문을 돌게 만든다. 그리고 다른 스레드에서 해당 스레드를 멈추게 하고 싶은 경우에 true로 초기화하게 만들어 멈추게 하자.
+
+ ```java
+ public class StopThread {
+ private static boolean stopRequested; // false 초기화
+ public static void main(String[] args) throws InterruptedException {
+
+ new Thread(() -> {
+ int i = 0;
+ while(!stopRequested){
+ i++;
+ }
+ }).start();
+
+ // 1초 뒤에 저 스레드를 멈추게 하자.
+ TimeUnit.SECONDS.sleep(1);
+ stopRequested = true;
+ }
+ }
+ ```
+
+
+
+
+
+
+**앗?? 왜 무한 루프지?**
+
+- 동기화의 두번째 기능. **스레드간의 통신**을 생각하지 않았기 때문이다.
+- 동기화하지 않으면, 메인 스레드가 수정한 값을 백그라운드 스레드가 언제쯤에나 보게 될지 보증할 수 없다 !
+- `synchronized` 를 사용해 동기화시키자.
+
+ ```java
+ public class StopThread {
+ private static boolean stopRequested;
+
+ // 쓰기 메서드
+ private static synchronized void requestStop() {
+ stopRequested = true;
+ }
+
+ // 읽기 메서드
+ private static synchronized boolean stopRequested() {
+ return stopRequested;
+ }
+
+ public static void main(String[] args) throws InterruptedException {
+ Thread backgroundThread = new Thread(() -> {
+ int i = 0;
+ while (!stopRequested()) {
+ i++;
+ }
+ });
+ backgroundThread.start();
+
+ TimeUnit.SECONDS.sleep(1);
+ requestStop();
+ }
+ }
+ ```
+
+쓰기 메서드와 읽기 메서드를 둘 다 동기화했음을 주목하자.
+
+- **쓰기 메서드, 읽기 메서드 둘 다 동기화하지 않으면 동작을 보장하지 않는다. 스레드간의 통신(Communication)의 동작을 보장하지 못한다.**
+
+
+
+
+
+위 코드에 `volatile` 을 사용하면 더 간단하게 작성할 수 있다.
+
+```java
+public class StopThread {
+ // volatile 사용
+ private static volatile boolean stopRequested;
+
+ public static void main(String[] args) throws InterruptedException {
+ new Thread(() -> {
+ int i = 0;
+ while (!stopRequested) {
+ i++;
+ }
+ }).start();
+
+ TimeUnit.SECONDS.sleep(1);
+ stopRequested = true;
+ }
+}
+```
+
+`volatile` 이 뭐야?: **데이터를 메인 메모리에 저장하겠다!**
+
+- '응? 그럼 그 전엔 메인 메모리에 저장안했나?'
+ - **Multi-thread 환경**에서는 task를 수행하는 동안 성능 향상을 위해 변수 데이터들을 Main memory에서 활용하는 것이 아닌 **CPU cache에 저장하고 활용**한다.
+
+ ![1](https://user-images.githubusercontent.com/37873745/112991414-0c2df500-91a2-11eb-89e3-0613139d33ef.png)
+
+ - 이런 구조였기에 Thread 간에 같은 변수에 접근하더라도 같은 값을 가지지 않고, 다른 값을 가질 수 있었던 것 → 즉, 동기화 문제의 이유 중 하나
+- 즉, `volatile`이 사용된 필드는 Multi thread 상황에서도 cache를 사용하지 않고 Main memory에 데이터를 저장하고 읽기에 위 문제 상황은 해결할 수 있다.
+
+
+
+
+그럼 애매한 건 다 `volatile` 써서 동기화 문제를 해결할 수 있는 것 아닐까?
+
+- 아니다! Write을 하기 이전에 Read를 해버리면 잘못된 값을 읽어올 수 있다.
+
+```java
+private static volatile int nextSerialNumber= 0;
+
+public static int generateSerialNumber(){
+ return nextSerialNumber++;
+}
+```
+
+- 각 Thread는 `generateSerialNumber` 값이 unique 값이라고 생각할 수 있지만, 한 Thread가 저장하기 이전에 읽어버리면 Thread 간 `generateSerialNumber`는 중복된 값이 된다 → Safety Failure (안전실패) 오류
+- 이 문제도 `synchronized` 를 붙이면 해결되며, 이러한 경우 `volatile` 메서드를 삭제하여야 한다.
+
+
+
+
+근데 보통 Primitive, Collection 같이 자주 사용되는 것에는 동기화를 지원하는 클래스들이 있다. → `java.util.concurrent` 참조
+
+- 작성하기 편하다. `synchronized` 같은 키워드를 사용하지 않아도 된다.
+- 성능도 기존 동기화를 수동으로 하는 것보다 우수하다.
+
+
+
+
+------
+
+# 하지만, 이러한 동기화 문제를 피하는 가장 좋은 방법은...
+
+애초에 가변 데이터를 공유하지 않는 것...
+
+- **불변 데이터만 공유하거나 아무것도 공유하지 말자 (Item 17)**
+- **가변 데이터는 단일 스레드에서만 사용하도록 하자.**
+- **문서화를 잘해서 동기화 문제가 일어나지 않도록 하자**
+ - `synchronized` 를 사용했다면, 다른 부분에서도 사용할 수 있도록
+ - 가변 데이터는 단일 스레드에서만 사용한다면, 멀티 스레드에서 사용하지 않도록 등
+- **사용하려는 프레임워크, 라이브러리가 스레드를 수행하는지 인지하고 사용하자.**
\ No newline at end of file