๐บ Naver Map sdk๋ฅผ ์ฌ์ฉํ์ฌ ์ง๋ํ๋ฉด์ ๊ฐ๋ฐํ๋ ์ค, Multithreading์ ๋ง๋๊ฒ ๋์๋ค.
์๋ฅผ๋ค์ด, ์ง๋์์ ์นดํ๋ฅผ ํด๋ฆญํ๋ฉด ์ง๋ ์์ ์นดํ ๋ง์ปค๊ฐ ์ฌ๋ฌ๊ฐ ๊ทธ๋ ค์ง๊ฒ ๋๋๋ฐ ๋ญ 100๊ฐ ์์ชฝ์ด๋ฉด ๊ทธ๋ฅ ๊ทธ๋ ค์ง ์ ์๊ฒ ๋ค.
๊ทผ๋ฐ ๋ง์ฝ ์ด ๋ง์ปค๊ฐ 100๊ฐ๋ฅผ ๋์ด์ 1000๊ฐ.. ์ด๋ ๊ฒ ๊ฐ๋ค๋ฉด ์ด๋ป๊ฒ ํ ๊น?
"์นดํ" ๊ฒ์๋ง ํ๊ณ ์ ๋ง ๋ง์ ์๊ฐ์ ๋ก๋ฉ์ ๊ธฐ๋ค๋ ค์ผ ๋ง์ปค๊ฐ ๋ค ๊ทธ๋ ค์ง ๊ฒ ์ด๋ค.
Naver Map์์ ๋งํ๋ ์ค๋ฒ๋ ์ด ๊ฐ์ฒด๋ ์๋ฌด ์ค๋ ๋์์๋ ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค๊ณ ํ๋ค.
๊ทธ๋ฌ๋ ์ค๋ฒ๋ ์ด ์์ฑ์ ์ค๋ ๋ ์์ ์ฑ์ด ๋ณด์ฅ๋์ง ์๊ธฐ์ ์ฌ๋ฌ ์ค๋ ๋์์ ๋์์ ์ ๊ทผํด์๋ ์๋๋ค.
โ
ํนํ, ์ง๋์ ์ถ๊ฐ๋ ์ค๋ฒ๋ ์ด์ ์์ฑ์ ๋ฉ์ธ ์ค๋ ๋์์๋ง ์ ๊ทผํด์ผ ํ๋ฉฐ, ๊ทธ๋ ์ง ์์ผ๋ฉด CalledFromWrongThreadException
์ ๋ฐ์์ํจ๋ค.
๋ฐ๋ผ์ ์์์ ๋งํ ๊ฒ์ฒ๋ผ ๋๋์ ์ค๋ฒ๋ ์ด ๊ฐ์ฒด๋ฅผ ๋ค๋ฃจ ๊ฒฝ์ฐ, ๊ฐ์ฒด ์์ฑ+์ด๊ธฐ์ต์ ์์ ์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ํํ๊ณ ์ง๋์ ์ถ๊ฐํ๋ ์์ ๋ง ๋ฉ์ธ ์ค๋ ๋์์ ์ํํด์ผ ํจ์จ์ ์ด๋ค.
์๋๋ ์์ ์ฝ๋์ด๋ค.
val executor: Executor = ...
val handler = Handler(Looper.getMainLooper())
executor.execute {
// ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋
val markers = mutableListOf<Marker>()
repeat(1000) {
markers += Marker().apply {
position = ...
icon = ...
captionText = ...
}
}
handler.post {
// ๋ฉ์ธ ์ค๋ ๋
markers.forEach { marker ->
marker.map = naverMap
}
}
}
์ด๋ ๊ฒ Naver Map์์ ์ค๋ฒ๋ ์ด ๊ฐ์ฒด ์ค๋ช ์ ๋ณด๋ค๊ฐ thread safeํ ๊ฐ๋ฐ์ด ์ค์ํ๋ค๋ ๊ฒ์ ์๊ณ ์ด๋ฅผ ์ข ๋ ์ ๋ฆฌํด๋ณด๊ณ ์ ํ๋ค.
์ค๋ ๋๊ฐ safeํ์ง ์์ ์ํ๋ผ๋ ๊ฒ์ ๋ฌด์์ด ์์๊น?
ํด๋น ๋ธ๋ก๊ทธ์ ์ข์ ์์ ๊ฐ ์์ด์ ๊ฐ์ ธ์๋ค.
public class CountingTest {
public static void main(String[] args) {
Count count = new Count();
for (int i = 0; i < 100; i++) {
new Thread(){
public void run(){
for (int j = 0; j < 100; j++) {
System.out.println(count.view());
}
}
}.start();
}
}
}
class Count {
private int count;
public int view() {return count++;}
public int getCount() {return count;}
}
์์ ์ฝ๋์์ ๋ณผ ์ ์๋ ๊ฒ์ฒ๋ผ, 100๋ช
์ ์ฌ๋์ด ๊ฐ๊ฐ 100๋ฒ์ฉ ์กฐํํ๊ณ ์ด๋ฅผ ์ถ๋ ฅํ๋ ์์คํ
์ด๋ค.
๊ทธ๋ผ ๋ฌด์กฐ๊ฑด 10000์ด ๋์์ผ ํ๋๋ฐ
์ฐธ์กฐ:https://deveric.tistory.com/104
๊ฒฐ๊ณผ๋ ๊ทธ๋ ์ง ์๋ค๊ณ ํ๋ค.
count๋ฅผ ์
๋ฐ์ดํธ ํ๋ ๋ก์ง์ 2๊ฐ์ง๋ก ๋๋์ด์ง๋ค.
1. ๊ธฐ์กด์ count๋ฅผ ์ฝ์ด์จ๋ค.
2. count์ +1์ ํด์ ๋ค์ ์ ์ฅํ๋ค.
1๋ฒ๊ณผ 2๋ฒ ์ฌ์ด์ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ๊ด์ฌํ๊ฒ ๋๋ฉด
๋๋ 22๋ฅผ ๊ฐ์ ธ์์ 23์ ๋ง๋ค์๋๋ฐ
๋ค๋ฅธ ์ค๋ ๋๋ 22๋ฅผ ๊ฐ์ ธ์์ 23์ ๋ง๋ค๊ฒ ๋๋ค.
๊ทธ๋ผ ์ผ๋จ ์์ ํ ๊ฒฝ์ฐ๋ง ์๊ฐํด๋ ์ต์ข
์ ์ผ๋ก 9999๊ฐ ๋์ฌ๊ฒ์ด๋ค..
์ฐ๋ฆฐ ์์ธกํ ์ ์๋ค. ์ค๋ ๋๊ฐ ์ธ์ ๋์์ ์ ๊ทผํด์ ์์ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ง ๐ญ
๊ฐ์ฅ ๊ฐ๋จํ๋ฉด์ ์ฌ์ด ๋ฐฉ๋ฒ์ Lock์ ๊ฑธ์ด ๋ฒ๋ฆฌ๋ ๊ฒ.
Lock์ด ์ ์ฉ๋๋ฉด ํ๋์ ์ค๋ ๋๊ฐ ํด๋น ๋ฉ์๋๋ฅผ ์คํ ์ค์ผ ๋ ๋ค๋ฅธ ๋ฉ์๋๊ฐ ํด๋น ๋ฉ์๋๋ฅผ ์คํํ์ง ๋ชปํ๊ณ ๋๊ธฐํ๊ฒ ๋๋ค.
1๋ฒ์ ํ๋์ ์ค๋ ๋๋ง ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค.
๋์์ฑ ์ด์๋ฅผ ๋ง์ ์ ์์ง๋ง ๋ณ๋ ฌ์ฑ์ ๋งค์ฐ ๋ฎ์์ง๋ค.๐ซ
๐ ์ด๋ป๊ฒ ์ฌ์ฉํ ๊น?
๋ฌธ์ ๊ฐ ๋ view๋ฉ์๋์ synchronized ํค์๋๋ฅผ ๋ถ์ด๋ฉด ์์์ ๋ฝ์ด ๊ฑธ๋ฆฐ๋ค.
Method Lock
class Count {
private int count;
public synchronized int view() {return count++;}
}
๋ณ์ Lock
class Count {
private Integer count = 0;
public int view() {
synchronized (this.count) {
return count++;
}
}
}
synchronized ํค์๋ ์์ด ๋ช ์์ ์ผ๋ก ReentrantLock์ ์ฌ์ฉํ๋ Lock.
public class CountingTest {
public static void main(String[] args) {
Count count = new Count();
for (int i = 0; i < 100; i++) {
new Thread(){
public void run(){
for (int j = 0; j < 1000; j++) {
count.getLock().lock();
System.out.println(count.view());
count.getLock().unlock();
}
}
}.start();
}
}
}
class Count {
private int count = 0;
private Lock lock = new ReentrantLock();
public int view() {
return count++;
}
public Lock getLock(){
return lock;
};
}
์์ ๊ฐ์ด Thread-Safe๋ฅผ ์งํค๋๋ฐ๋ 5๊ฐ์ง ์์น์ด ์๋ค.
Atomic
: ๋ฐ์ดํฐ์ ๋ณ๊ฒฝ์ด ๋์์ ์ผ์ด๋ ๊ฒ ์ฒ๋ผ ๋ณด์ด๊ฒ ํ๋ ๊ฒ.
๋ฐ์ดํฐ์ ๊ฐ์ ๋ณ๊ฒฝํ๋ ๊ฒ์ ์๊ฐ์ด ํ์ํ๊ธฐ์ atomicํ ๋ฐ์ดํฐ์ ๋ณ๊ฒฝ์ด ์ด๋ฃจ์ด์ง๋ ์๊ฐ์๋ lock์ ๊ฑด๋ค. ๊ทธ๋์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ์๊ฐ๋์ ์ ๊ทผ์ด ์ด๋ฃจ์ด์ง์ง ์๋๋ค.
A,B๊ฐ ๋์์ ์คํ ๋ ๋, ๋์ ์ ๊ทผ์ด ์๋๊ธฐ์ ์คํ ์์ ํน์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ ๋ํด์ ๋๊ธฐํ๋ฅผ ์ํํ๋ค. (๊ด์ ์ ๋ฐ๋ผ 2๊ฐ๋ก ๋๋์ด์ง๋ค)
: ์ค๋ ๋์ ์คํ ์์๋ฅผ ์ ์ํ๊ณ , ๋ฐ๋์ ์ด ์์๋ฅผ ๋ฐ๋ฅด๋๋ก ํ๋ค.
: ๋ฐ์ดํฐ ์์ญ๊ณผ ํ ์์ญ๊ณผ ๊ฐ์ด ํ ์๊ฐ์ ํ๋์ ์ค๋ ๋๋ง ์ ๊ทผํ๋๋ก ํ๋ ๊ฒ์ด ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ ๋ํ ๋๊ธฐํ.
: ๋ง์ฝ 2๊ฐ์ ์ค๋ ๋๊ฐ ๋์์ ๋ฐ์ดํฐ ์ ๊ทผํ์ฌ ๋ณ๊ฒฝํ๋ค๋ฉด ๊ณ์ฐ ๊ฒฐ๊ณผ๊ฐ ๋ฎ์ฌ์์์ง๋ ์ฌ๋ฌ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
์ค๋ ๋์ ๋์์ฑ์ ์ด์ผ๊ธฐํ๋ค๋ณด๋ฉด volatile ์ด์ผ๊ธฐ๋ ๋์จ๋ค.
์์์ ์ฃผ๊ตฌ์ฅ์ฐฝ ์ด์ผ๊ธฐ ํ ๊ฒ ์ฒ๋ผ, ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๊ณต์ ์์์ ์ ๊ทผ์ ํ ๋ ์ด๋ฅผ ๋ฌด๋ถ๋ณํ๊ฒ ์ ๊ทผ์ํค๋ฉด ์ค๋ฅ๊ฐ ๋งค์ฐ ๋ง์ด ๋๊ณ ์์น ์๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํดํ๊ฒ ๋๋ค. ๊ทธ๋์ thread-safeํ๊ฒ ํ๋ก๊ทธ๋๋ฐ์ ํ๋๊ฒ ์ค์ํ๋ค๊ณ ํ๋ค.
๊ทผ๋ฐ ๊ทธ๋ ๋ค๋ฉด ์ค๋ ๋๊ฐ ์ ๊ทผํ๋ ๋ฐ์ดํฐ๋ ๋ชจ๋ ๋ฉ๋ชจ๋ฆฌ์ ์กด์ฌํ ๊น?
์ ๋ต์ ์๋๋ค. CPU์บ์์ ๊ฐ์ ์ ์ฅํ๊ธฐ๋ ํ๋ค.
๊ทธ๋์ ํด๋น ๋ฐ์ดํฐ๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋ ์ค์ ๋ฐ์ดํฐ์ ํญ์ ์ผ์นํ ์ง ๋ณด์ฅํ์ง ๋ชปํ๋ค.
๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ์์ ์ ์ฅ๋ ์ค์ ์์์ ๊ฐ์ ๋ณผ ์ ์๋ ๊ฐ๋
์ ์์์ ๊ฐ์์ฑ์ด๋ผ๊ณ ํ๋๋ฐ ์ด๋ฅผ ์ถฉ์กฑ์ํค์ง ๋ชปํ ๊ฒฝ์ฐ๋ค.
volatile์ CPU ์บ์ ์ฌ์ฉ์ ๋ง๋๋ค. ํค์๋๋ก ๋ถ๊ฒ ๋๋ฉด ํด๋น ๋ณ์๋ ์บ์์ ์ ์ฅ๋์ง ์๋๋ค. ๋ฐ์ดํฐ ๋ถ์ผ์น๋ฅผ ๋ง๊ธฐ ์ํด ๋งค๋ฒ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋๋ค.
๊ทธ๋์ volatile์ ์์์ ๊ฐ์์ฑ์ ํ๋ณดํด์ฃผ์ง๋ง ๋์์ฑ ์ด์๋ฅผ ํด๊ฒฐํ๊ธฐ์ ๋ถ์กฑํ๋ค. read&write ์์ ์ ๋๊ธฐํ๋ฅผ ํ ๋ ํด๋น ์ฐ์ฐ์ด ์์์ฑ์ ์ด๋ฃจ๋๋ก ์ค์ ํด์ค์ผ ๋น๋ก์ ๋์์ฑ ์ด์๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
2๊ฐ์ ์ค๋ ๋๊ฐ ์๊ณ ํ ์ค๋ ๋๋ read๋ง, ํ ์ค๋ ๋๋ write๋ง ํ ๊ฒฝ์ฐ.
read๋ง ํ๋ ์ค๋ ๋๋ cpu์บ์์์ ๊ฐ์ ํ์ธํ ํ
๋ฐ write๋ง ํ๋ ์ค๋ ๋๊ฐ ๋ฃ์ ๊ฐ์ ๋ฐ๋ก ํ์ธํ์ง ๋ชปํ ์ ์๋ค.
์ด๋ด ๊ฒฝ์ฐ, volatile์ ๋ถ์ฌ ๋ ์ค๋ ๋๊ฐ ์ฐ๊ณ ์ฝ๋ ๊ฐ์ ์์์ฑ์ ํ๋ณดํ ์ ์๋ค. ๋์์ฑ ์ด์ ์ญ์ ํด๊ฒฐ ๊ฐ๋ฅํ๋ค.
โ CPU์บ์๋ฅผ ๋นํ์ฑํ ํ๊ณ ๋งค๋ฒ ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผํ๊ธฐ์ ์ฑ๋ฅ ์ ํ๊ฐ ๋น์ฐํ ๋ฐ์ํ๊ธฐ์ ์ ์ํด์ volatile์ ์จ์ผํ๋ค.