From e3f0069702f89eb4a637c3525c2320ca9dbb99d0 Mon Sep 17 00:00:00 2001 From: ezhoon Date: Sat, 22 Apr 2023 22:28:33 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[rxJava=20=EC=8A=A4=ED=84=B0=EB=94=94=20-?= =?UTF-8?q?=202=EC=9E=A5]=202=EC=9E=A5=20=EC=98=88=EC=A0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/ezhoon/chapter02/2-11.kt | 14 ++++++++++ src/main/kotlin/ezhoon/chapter02/2-12.kt | 27 +++++++++++++++++++ src/main/kotlin/ezhoon/chapter02/2-13-2.kt | 31 ++++++++++++++++++++++ src/main/kotlin/ezhoon/chapter02/2-13.kt | 18 +++++++++++++ src/main/kotlin/ezhoon/chapter02/2-5.kt | 12 +++++++++ src/main/kotlin/ezhoon/chapter02/2-6.kt | 27 +++++++++++++++++++ src/main/kotlin/ezhoon/chapter02/README.md | 0 7 files changed, 129 insertions(+) create mode 100644 src/main/kotlin/ezhoon/chapter02/2-11.kt create mode 100644 src/main/kotlin/ezhoon/chapter02/2-12.kt create mode 100644 src/main/kotlin/ezhoon/chapter02/2-13-2.kt create mode 100644 src/main/kotlin/ezhoon/chapter02/2-13.kt create mode 100644 src/main/kotlin/ezhoon/chapter02/2-5.kt create mode 100644 src/main/kotlin/ezhoon/chapter02/2-6.kt create mode 100644 src/main/kotlin/ezhoon/chapter02/README.md diff --git a/src/main/kotlin/ezhoon/chapter02/2-11.kt b/src/main/kotlin/ezhoon/chapter02/2-11.kt new file mode 100644 index 0000000..c9bc15f --- /dev/null +++ b/src/main/kotlin/ezhoon/chapter02/2-11.kt @@ -0,0 +1,14 @@ +package ezhoon.chapter02 + +import java.util.concurrent.atomic.AtomicInteger + +class AtomicConsumer { + + @Volatile + var count = AtomicInteger(0) + private set + + fun increment() { + count.incrementAndGet() + } +} \ No newline at end of file diff --git a/src/main/kotlin/ezhoon/chapter02/2-12.kt b/src/main/kotlin/ezhoon/chapter02/2-12.kt new file mode 100644 index 0000000..86dbd0c --- /dev/null +++ b/src/main/kotlin/ezhoon/chapter02/2-12.kt @@ -0,0 +1,27 @@ +package ezhoon.chapter02 + +import java.util.concurrent.Executors + +fun main() { + + val counter = AtomicConsumer() + + val task = Runnable { + for (i in 0..9999) { + counter.increment() + } + } + + val executorService = Executors.newCachedThreadPool() + + val future1 = executorService.submit(task, true) + val future2 = executorService.submit(task, true) + + if (future1.get() && future2.get()) { + println("${counter.count}") + } else { + println("실패") + } + + executorService.shutdown() +} \ No newline at end of file diff --git a/src/main/kotlin/ezhoon/chapter02/2-13-2.kt b/src/main/kotlin/ezhoon/chapter02/2-13-2.kt new file mode 100644 index 0000000..f73a5f5 --- /dev/null +++ b/src/main/kotlin/ezhoon/chapter02/2-13-2.kt @@ -0,0 +1,31 @@ +package ezhoon.chapter02 + +import java.util.concurrent.Executors + +fun main() { + + val point = Point() + + val task = Runnable { + for (i in 0..9999) { + point.rightUp() + } + } + + val executorService = Executors.newCachedThreadPool() + + val future1 = executorService.submit(task, true) + val future2 = executorService.submit(task, true) + val future3 = executorService.submit(task, true) + val future4 = executorService.submit(task, true) + val future5 = executorService.submit(task, true) + val future6 = executorService.submit(task, true) + + if (future1.get() && future2.get() && future3.get() && future4.get() && future5.get() && future6.get()) { + println("${point.getX()},${point.getY()}") + } else { + println("실패") + } + + executorService.shutdown() +} \ No newline at end of file diff --git a/src/main/kotlin/ezhoon/chapter02/2-13.kt b/src/main/kotlin/ezhoon/chapter02/2-13.kt new file mode 100644 index 0000000..9a7e1eb --- /dev/null +++ b/src/main/kotlin/ezhoon/chapter02/2-13.kt @@ -0,0 +1,18 @@ +package ezhoon.chapter02 + +import java.util.concurrent.atomic.AtomicInteger + +class Point { + + private val x = AtomicInteger(0) + private val y = AtomicInteger(0) + + fun rightUp() { + x.incrementAndGet() + y.incrementAndGet() + } + + fun getX() = x.get() + + fun getY() = y.get() +} \ No newline at end of file diff --git a/src/main/kotlin/ezhoon/chapter02/2-5.kt b/src/main/kotlin/ezhoon/chapter02/2-5.kt new file mode 100644 index 0000000..5534052 --- /dev/null +++ b/src/main/kotlin/ezhoon/chapter02/2-5.kt @@ -0,0 +1,12 @@ +package ezhoon.chapter02 + +class Consumer { + + @Volatile + var count: Int = 0 + private set + + fun increment() { + count++ + } +} \ No newline at end of file diff --git a/src/main/kotlin/ezhoon/chapter02/2-6.kt b/src/main/kotlin/ezhoon/chapter02/2-6.kt new file mode 100644 index 0000000..c53e958 --- /dev/null +++ b/src/main/kotlin/ezhoon/chapter02/2-6.kt @@ -0,0 +1,27 @@ +package ezhoon.chapter02 + +import java.util.concurrent.Executors + +fun main() { + + val counter = Consumer() + + val task = Runnable { + for (i in 0..9999) { + counter.increment() + } + } + + val executorService = Executors.newCachedThreadPool() + + val future1 = executorService.submit(task, true) + val future2 = executorService.submit(task, true) + + if (future1.get() && future2.get()) { + println("${counter.count}") + } else { + println("실패") + } + + executorService.shutdown() +} \ No newline at end of file diff --git a/src/main/kotlin/ezhoon/chapter02/README.md b/src/main/kotlin/ezhoon/chapter02/README.md new file mode 100644 index 0000000..e69de29 From 4f8866a78c5411c586f29428bba057102b497726 Mon Sep 17 00:00:00 2001 From: ezhoon Date: Sat, 22 Apr 2023 22:28:44 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[rxJava=20=EC=8A=A4=ED=84=B0=EB=94=94=20-?= =?UTF-8?q?=202=EC=9E=A5]=202=EC=9E=A5=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/ezhoon/chapter02/README.md | 79 ++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/src/main/kotlin/ezhoon/chapter02/README.md b/src/main/kotlin/ezhoon/chapter02/README.md index e69de29..71b9605 100644 --- a/src/main/kotlin/ezhoon/chapter02/README.md +++ b/src/main/kotlin/ezhoon/chapter02/README.md @@ -0,0 +1,79 @@ +## 람다식 + +> 함수형 인터페이스를 구현하기 위해 자바 8에서 도입한 표현식이다. + +`( ) -> { 실행문 }` + +### 함수형 인터페이스 + +| 인터페이스 | 설명 | +|--------------------|------------------------------| +| Function/Predicate | 인자를 전달받아 반환값을 반환하는 인터페이스 | +| BooleanSupplier | 인자 없이 반환값을 반환하는 인터페이스 | +| Action/Consumer | 반환값이 없는 인터페이스 | +| Cancellable | Action과 동일하나 실행 의미가 다른 인터페이스 | + +## 비동기 처리 + +> 어떤 작업을 실행하는 동안에 해당 처리가 끝나기를 기다리지 않고 다른 작업을 시작할 수 있는 것 + + +### 멀티 스레딩 + +> 스레드가 여러 개 존재할 때, 각각의 스레드에서 작업을 실행해 비동기 처리할 수 있다. + +- 작업 1, 2, 3을 실행하는 프로그램이 존재한다. +- 하나의 싱글 스레드로 한다면 + - 1 -> 2 -> 3 이렇게 순차적으로 진행이 될 것이다. +- 3개의 스레드가 있다면 + - 1을 수행하다가 중간에 멈추고 2를 하고 중간에 멈추고 3을 하는 것이 가능해진다. + - 위의 싱글 스레드와 비슷하지만 네트워크 통신이나 DB 작업 같은 경우에는 유의미한 결과가 나온다. +- 멀티 프로세스라면 + - 1, 2, 3이 거의 동시에 시작을 하고 작업의 양에 따라 끝나는 시점이 다르다. + +> 근데 단일 프로세스여도 멀티 스레드면 그냥 동시에 시작이 가능하지 않나? 안되나? +> 백그라운드 스레드만 가능했던건가? + +## 비동기 처리 시 주의할 점 +> 싱글 스레드에서는 생각하지 않아도 되는 것들을 비동기 시점에선 알아야 할 것들이 존재하게 된다. + +### 메모리와 캐시 + +- 클래스 필드가 가리키는 값과 실제 메모리가 가리키는 값이 동일하지 않을 수 있다. +- 필드가 다르는 값은 메모리에서 캐시된 값이다. 이 값을 변경하고 적절한 시점에 실제 메모리에 반영을한다. + - 여기서 주의해야 할 점이 적절한 시점이다. + - 만약 내가 반영하기 전에 다른 작업이 해당 값을 사용을 하게 된다면 문제가 될 것이다. + +### 원자성 +> 일련의 처리 흐름 중간에 다른 작업이 끼어들 가능성이 있는지 고려해야 하며 이 일련의 처리가 분할할 수 없게 되어 있는 것을 원장성이라고 한다. + +- 비동기 처리에서는 특정 메서드를 실행하는 동안 다른 작업이 실행된다. +- 그러므로 필드에 접근하면 원장성이 깨지게 될 수 있다. + +### 2-6 예제에서 매번 값이 다른 이유 + + + +> 위의 사진과 비슷한 이치이다. + +read -> modify -> write + +- count의 값을 갖고 온다. +- 1을 더한다. +- count를 설정한다. + +근데 두 개의 스레드가 동시에 count 값을 갖고 오거나 write 되기 전의 값을 갖고와서 작업을 하기에 문제가 되는 것이다. + +## 비동기 처리 시 발생하는 문제에 대한 대응 방안 + +> 여러가지가 존재하는데 키워드로만 정리할 예정이다. + +- final 제한자와 불변 객체 +- Volatile + - 최신 메모리 값을 갖고 오는 것을 보장한다. + - 하지만 이 제한자는 최신 값을 갖고 올 뿐 업데이트할 때 원자성을 보장하지 않는다. +- Atomic + - 2-11, 2-12 예제 참고 +- Synchronized + +