๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ“š์ฝ์€ ์ฑ… ์ •๋ฆฌ/์ดํŽ™ํ‹ฐ๋ธŒ์ž๋ฐ”

[์ดํŽ™ํ‹ฐ๋ธŒ ์ž๋ฐ”] 11์žฅ : ๋™์‹œ์„ฑ

์Šค๋ ˆ๋“œ๋Š” ์—ฌ๋Ÿฌ ํ™œ๋™์„ ๋™์‹œ์— ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค. ํ•˜์ง€๋งŒ ๋™์‹œ์„ฑํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์–ด๋ ต๊ณ  ์ž˜๋ชป๋  ์ˆ˜ ์žˆ๋Š” ์ผ์ด ๋Š˜์–ด๋‚˜๋ฉฐ ๋ฌธ์ œ๋ฅผ ์žฌํ˜„ํ•˜๊ธฐ๋„ ์–ด๋ ต๋‹ค (๋””๋ฒ„๊น…์ด ์–ด๋ ต๋‹ค)

ํ•˜์ง€๋งŒ, ์–ด๋ ต๋‹ค๊ณ  ํ”ผํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค. ์˜ค๋Š˜๋‚  ๋„๋ฆฌ ์“ฐ์ด๋Š” ๋‹ค์ค‘์ฝ”์–ด ํ”„๋กœ์„ธ์„œ์˜ ํž˜์„ ์ œ๋Œ€๋กœ ํ™œ์šฉํ•˜๋ ค๋ฉด ๋ฐ˜๋“œ์‹œ ๋‚ด๊ฒƒ์œผ๋กœ ๋งŒ๋“ค์–ด์•ผ๋งŒ ํ•˜๋Š” ๊ธฐ์ˆ ์ด๋‹ค.

์•„์ดํ…œ 78 : ๊ณต์œ  ์ค‘์ธ ๊ฐ€๋ณ€ ๋ฐ์ดํ„ฐ๋Š” ๋™๊ธฐํ™”ํ•ด ์‚ฌ์šฉํ•˜๋ผ

๋™๊ธฐํ™”์˜ ๊ธฐ๋Šฅ

  • ๋ฐฐํƒ€์  ์‹คํ–‰

๋งŽ์€ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ๋™๊ธฐํ™”๋ฅผ ๋ฐฐํƒ€์  ์‹คํ–‰, ์ฆ‰ ํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ณ€๊ฒฝํ•˜๋Š” ์ค‘์ด๋ผ์„œ ์ƒํƒœ๊ฐ€ ์ผ๊ด€๋˜์ง€ ์•Š์€ ์ˆœ๊ฐ„์˜ ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ณด์ง€ ๋ชปํ•˜๊ฒŒ ๋ง‰๋Š” ์šฉ๋„๋กœ๋งŒ ์ƒ๊ฐํ•œ๋‹ค.

์ผ๊ด€๋œ ๊ฐ์ฒด ์ƒ์„ฑ → ์ ‘๊ทผํ•˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ๊ฐ์ฒด์— ๋ฝ์„ ๊ฒ€ → ๋ฝ์„ ๊ฑด ๋ฉ”์„œ๋“œ๊ฐ€ ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๊ณ  ์ˆ˜์ •ํ•จ ⇒ ๊ฐ์ฒด๋ฅผ ํ•˜๋‚˜์˜ ์ผ๊ด€๋œ ์ƒํƒœ์—์„œ ๋‹ค๋ฅธ ์ผ๊ด€๋œ ์ƒํƒœ๋กœ ๋ณ€ํ™”์‹œํ‚ค๋Š” ๊ณผ์ •

๋™๊ธฐํ™”๋ฅผ ์ œ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์–ด๋–ค ๋ฉ”์„œ๋“œ๋„ ์ด ๊ฐ์ฒด์˜ ์ƒํƒœ๊ฐ€ ์ผ๊ด€๋˜์ง€ ์•Š์€ ์ˆœ๊ฐ„์„ ๋ณผ ์ˆ˜ ์—†๋‹ค.

๋™๊ธฐํ™”์˜ ๋˜ ๋‹ค๋ฅธ ์ค‘์š”ํ•œ ๊ธฐ๋Šฅ! → ๋™๊ธฐํ™”๋Š” ์Šค๋ ˆ๋“œ ์‚ฌ์ด์˜ ์•ˆ์ •์ ์ธ ํ†ต์‹ ์— ๊ผญ ํ•„์š”ํ•˜๋‹ค.

  • ์Šค๋ ˆ๋“œ ์‚ฌ์ด์˜ ์•ˆ์ •์ ์ธ ํ†ต์‹ 

๊ณต์œ ์ค‘์ธ ๊ฐ€๋ณ€ ๋ฐ์ดํ„ฐ๊ฐ€ ์›์ž์ (long, double..)์œผ๋กœ ์ฝ๊ณ  ์“ธ ์ˆ˜ ์ฝ์„์ง€๋ผ๋„ ๋™๊ธฐํ™”์— ์‹คํŒจํ•˜๋ฉด ์ฒ˜์ฐธํ•œ ๊ฒฐ๊ณผ๋กœ ์ด์–ด์ง„๋‹ค.

public class StopThread {
  	private static boolean stopRequested;
  
  	public static void main(String[] args) {
      	Thread backgroundThread = new Thread(() -> {
          int i = 0;
          while (!stopRequested) // ํŠน์ • ๊ฐ€์ƒ๋จธ์‹ ์ด ์ตœ์ ํ™” ์ˆ˜ํ–‰ํ•˜๋ฉด ๋ฌดํ•œํžˆ ์‹คํ–‰๋จ. ์Šค๋ ˆ๋“œ๊ฐ„ ํ†ต์‹  ๋ถˆ๊ฐ€๋Šฅ
            	i++;
        })
        backgroundThread.start();
      	
      	TimeUnit.SECONDS.sleep(1);
      	stopRequested = true;
    }
}

์œ„ ์ฝ”๋“œ๋Š” ๋ฉ”์ธ์“ฐ๋ ˆ๋“œ๊ฐ€ ๊ณต์œ ๋ณ€์ˆ˜๋ฅผ true๋กœ ๋ฐ”๊พธ๋ฉด 1์ดˆ์•ˆ์— ๋ฐฑ๊ทธ๋ผ์šด๋“œ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋˜๊ธธ ๊ธฐ๋Œ€ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ๊ณ„์†ํ•ด์„œ ๋Œ์•„๊ฐ„๋‹ค.

๊ทธ ์›์ธ์€ ๋™๊ธฐํ™”์ด๋‹ค. ๋™๊ธฐํ™”ํ•˜์ง€์•Š์œผ๋ฉด ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๊ฐ€ ์ˆ˜์ •ํ•œ ๊ฐ’์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ๊ฐ€ ์–ด๋Š ์‹œ์ ์— ๋ณด๊ฒŒ ๋ ์ง€ ๋ณด์žฅํ•  ์ˆ˜ ์—†๋‹ค. ๋˜ํ•œ ์ตœ์ ํ™”๊ฐ€ ์ง„ํ–‰๋˜์–ด ์˜ˆ์ƒ๊ณผ ๋‹ค๋ฅธ ํ๋ฆ„์œผ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

  • ์ตœ์ ํ™”๋กœ ํ๋ฆ„์ด ๋‹ฌ๋ผ์ง„ ์ฝ”๋“œ
// ์›๋ž˜ ์ฝ”๋“œ
while (!stopRequested)
	i++;

// ์ตœ์ ํ™” ์ฝ”๋“œ
if (!stopRequuested)
	while(true)
		i++;

์ตœ์ ํ™”๋กœ ์ธํ•ด ๊ณต์œ  ๋ณ€์ˆ˜ ๊ฐ’์ด ๋ฐ”๊ปด๋„ ์ค‘์ง€๋˜์ง€ ์•Š๊ณ  ์‹คํ–‰๋œ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ์“ฐ๊ธฐ ๋ฉ”์„œ๋“œ์™€ ์ฝ๊ธฐ ๋ฉ”์„œ๋“œ ๋ชจ๋‘๋ฅผ ๋™๊ธฐํ™”ํ•ด์•ผ๋งŒ ํ•œ๋‹ค.

→ ์“ฐ๊ธฐ์™€ ์ฝ๊ธฐ ๋ชจ๋‘๊ฐ€ ๋™๊ธฐํ™”๋˜์ง€ ์•Š์œผ๋ฉด ๋™์ž‘์„ ๋ณด์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.

private static synchronized void requestStop() {
  	stopRequested = true;
}
private static synchronized boolean stopRequested() {
  	return stopRequested;
}
public static void main(String[] args) {
  Thread backgroundThread = new Thread(() -> {
    int i = 0;
    while (!stopRequested())
      i++;
  })
    backgroundThread.start();

  TimeUnit.SECONDS.sleep(1);
	requestStop();
}

์œ„ ์ฝ”๋“œ๋Š” ๋™๊ธฐํ™”์˜ ๊ธฐ๋Šฅ ์ค‘ ์Šค๋ ˆ๋“œ ๊ฐ„ ํ†ต์‹  ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜์—ˆ๋‹ค.

volatile

์œ„ ์ฝ”๋“œ์—์„œ ๊ณต์œ ๋ณ€์ˆ˜๋ฅผ volatile ๋กœ ์„ ์–ธํ•˜๋ฉด ๋™๊ธฐํ™”๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฐฐํƒ€์  ์ˆ˜ํ–‰๊ณผ๋Š” ์ƒ๊ด€ ์—†์œผ๋‚˜, ํ•ญ์ƒ ๊ฐ€์žฅ ์ตœ๊ทผ์— ๊ธฐ๋ก๋œ ๊ฐ’์„ ์ฝ๊ฒŒ ๋จ์„ ๋ณด์žฅํ•œ๋‹ค.

  • ๋ฐฐํƒ€์  ์‹คํ–‰์„ ๋ณด์žฅํ•˜์ง€ ์•Š์œผ๋‚˜ ์Šค๋ ˆ๋“œ๊ฐ„ ํ†ต์‹ ์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ

์ฆ๊ฐ์—ฐ์‚ฐ์ž

์ฆ๊ฐ์—ฐ์‚ฐ์ž๋Š” atomicํ•˜์ง€ ์•Š๋‹ค. ์ด ์—ฐ์‚ฐ์ž๋Š” ์‹ค์ œ๋กœ ํ•„๋“œ์— ์ ‘๊ทผํ•ด 1)๊ฐ’์„ ์ฝ๊ณ  ๊ฐ’์„ ์ฆ๊ฐ์‹œ์ผœ 2)์ƒˆ๋กœ์šด ๊ฐ’์„ ์ €์žฅํ•œ๋‹ค.

์ด ๋‘ ์ ‘๊ทผ ์‚ฌ์ด์— ๋“ค์–ด์™€ ๊ฐ’์„ ์ฝ์–ด๊ฐ€๋ฉด ํ”„๋กœ๊ทธ๋žจ์ด ์ž˜๋ชป๋œ ๊ฒฐ๊ณผ๋ฅผ ๊ณ„์‚ฐํ•ด๋‚ด๋Š” ‘์•ˆ์ „ ์‹คํŒจ'๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์ด๋•Œ ์ฆ๊ฐ์—ฐ์‚ฐ์ž๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š” ๋ฉ”์„œ๋“œ์— synchronized ํ•œ์ •์ž๋ฅผ ๋ถ™์ด๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋œ๋‹ค. (๋Œ€์‹  ๋ณ€์ˆ˜์— volatile์€ ์‚ญ์ œ)

AtomicLong

AtomicLong์€ ๋ฝ ์—†์ด๋„ ์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•œ๋‹ค

  • ๋ฐฐํƒ€์  ์‹คํ–‰(์›์ž์„ฑ)๋„ ๋ณด์žฅํ•˜๊ณ , ์Šค๋ ˆ๋“œ๊ฐ„ ํ†ต์‹ ๋„ ๋ณด์žฅํ•œ๋‹ค.

์˜ˆ์‹œ๋กœ๋Š” getAndIncrement() ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค. (์•ˆ์ „ํ•œ ์ฆ๊ฐ์—ฐ์‚ฐ)

๋™์‹œ์„ฑ ๋ฌธ์ œ๋ฅผ ํ”ผํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ์• ์ดˆ์— ๊ฐ€๋ณ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด๋‹ค. (๋ถˆ๋ณ€ ๋ฐ์ดํ„ฐ๋งŒ ๊ณต์œ ํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค) ⇒ ๊ฐ€๋ณ€ ๋ฐ์ดํ„ฐ๋Š” ๋‹จ์ผ ์Šค๋ ˆ๋“œ์—์„œ๋งŒ ์“ฐ๋„๋ก ํ•˜์ž.

-ํ•ต์‹ฌ ์ •๋ฆฌ- : ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ€๋ณ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•œ๋‹ค๋ฉด ๊ทธ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ  ์“ฐ๋Š” ๋™์ž‘ ๋ชจ๋‘๋ฅผ ๋ฐ˜๋“œ์‹œ ๋™๊ธฐํ™” ํ•ด์•ผํ•œ๋‹ค.

์•„์ดํ…œ 79 : ๊ณผ๋„ํ•œ ๋™๊ธฐํ™”๋Š” ํ”ผํ•˜๋ผ

๊ณผ๋„ํ•œ ๋™๊ธฐํ™”๋Š” ์„ฑ๋Šฅ์„ ๋–จ์–ด๋œจ๋ฆฌ๊ณ , ๊ต์ฐฉ์ƒํƒœ์— ๋น ๋œจ๋ฆฌ๋ฉฐ, ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋Š” ๋™์ž‘์„ ์•ผ๊ธฐํ•œ๋‹ค.

  • ์‘๋‹ต ๋ถˆ๊ฐ€์™€ ์•ˆ์ „ ์‹คํŒจ๋ฅผ(๋™์‹œ์„ฑ ๋ฌธ์ œ) ํ”ผํ•˜๋ ค๋ฉด ๋™๊ธฐํ™” ๋ฉ”์„œ๋“œ๋‚˜ ๋™๊ธฐํ™” ๋ธ”๋ก ์•ˆ์—์„œ๋Š” ์ œ์–ด๋ฅผ ์ ˆ๋Œ€๋กœ ํด๋ผ์ด์–ธํŠธ์— ์–‘๋„ํ•˜๋ฉด ์•ˆ๋œ๋‹ค.
    • ์˜ค๋ฒ„๋ผ์ด๋”ฉ ๊ฐ€๋Šฅํ•œ ๋ฉ”์„œ๋“œ๋Š” ํ˜ธ์ถœํ•˜๋ฉด ์•ˆ๋œ๋‹ค
    • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋„˜๊ฒจ์ค€ ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์•ˆ๋œ๋‹ค.
  • ๋™๊ธฐํ™” ์˜์—ญ์—์„œ๋Š” ๊ฐ€๋Šฅํ•œ ์ผ์„ ์ ๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
    • ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์ด๋ผ๋ฉด ๋™๊ธฐํ™” ์˜์—ญ ๋ฐ–์œผ๋กœ ์˜ฎ๊ฒจ๋ณด์ž.
    • ๋™๊ธฐํ™”๊ฐ€ ๊ธธ์–ด์งˆ์ˆ˜๋ก ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ•  ๊ธฐํšŒ๋ฅผ ์ฝ๊ณ  ์ฝ”๋“œ ์ตœ์ ํ™” ๊ธฐํšŒ๋„ ์žƒ๊ฒŒ ๋œ๋‹ค.
  • ๊ฐ€๋ณ€ ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•˜๋ ค๊ฑฐ๋“  ๋‹ค์Œ ๋‘ ์„ ํƒ์ง€ ์ค‘ ํ•˜๋‚˜๋ฅผ ๋”ฐ๋ฅด์ž.
    1. ๋™๊ธฐํ™”๋ฅผ ํ•˜์ง€ ๋ง๊ณ , ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ๋™์‹œ์— ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ํด๋ž˜์Šค๊ฐ€ ์™ธ๋ถ€์—์„œ ์•Œ์•„์„œ ๋™๊ธฐํ™”ํ•˜๊ฒŒ ํ•˜์ž (StringBuilder)
    2. ๋™๊ธฐํ™”๋ฅผ ๋‚ด๋ถ€์—์„œ ์ˆ˜ํ–‰ํ•ด ์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•œ ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค์ž. (StringBuffer)

์„ ํƒํ•˜๊ธฐ ์–ด๋ ต๋‹ค๋ฉด ๋™๊ธฐํ™” ํ•˜์ง€๋ง๊ณ  ๋ฌธ์„œ์— ‘์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•˜์ง€ ์•Š๋‹ค'๊ณ  ๋ช…๊ธฐํ•˜์ž.

์•„์ดํ…œ 80 : ์Šค๋ ˆ๋“œ๋ณด๋‹ค๋Š” ์‹คํ–‰์ž, ํƒœ์Šคํฌ, ์ŠคํŠธ๋ฆผ์„ ์• ์šฉํ•˜๋ผ

์‹คํ–‰์ž(Excutor)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ž‘์—… ํ๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ƒ์„ฑํ•˜๊ณ  ์Šค๋ ˆ๋“œ ํ’€์„ ์ƒ์„ฑํ•ด ์—ฌ๋Ÿฌ ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๋ฅผ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.

  • Task๋ž€ ์ž‘์—…๋‹จ์œ„๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํ•ต์‹ฌ ์ถ”์ƒ ๊ฐœ๋…
    • Runnable (์‹คํ–‰)
    • Callable (๊ฐ’์„ ๋ฐ˜ํ™˜, ์˜ˆ์™ธ๋ฅผ ๋˜์งˆ ์ˆ˜ ์žˆ์Œ)

์ž‘์—… ํ๋ฅผ ์†์ˆ˜ ๋งŒ๋“œ๋Š” ์ผ์€ ์‚ผ๊ฐ€์•ผํ•˜๊ณ , ์Šค๋ ˆ๋“œ๋ฅผ ์ง์ ‘ ๋‹ค๋ฃจ๋Š” ๊ฒƒ๋„ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ผ๊ฐ€์•ผํ•œ๋‹ค. ๋ฐ˜๋ฉด ์‹คํ–‰์ž ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” ์ž‘์—…๋‹จ์œ„์™€ ์‹คํ–‰ ๋งค์ปค๋‹ˆ์ฆ˜์ด ๋ถ„๋ฆฌ๋œ๋‹ค.

์•„์ดํ…œ 81 : wait์™€ notify๋ณด๋‹ค๋Š” ๋™์‹œ์„ฑ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์• ์šฉํ•˜๋ผ

wait์™€ notify๋Š” ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ๊ฐ€ ์•„์ฃผ ๊นŒ๋‹ค๋กœ์šฐ๋‹ˆ ๊ณ ์ˆ˜์ค€ ๋™์‹œ์„ฑ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์ž.

java.util.concurrent์˜ ๊ณ ์ˆ˜์ค€ ์œ ํ‹ธ๋ฆฌํ‹ฐ

  • ์‹คํ–‰์ž ํ”„๋ ˆ์ž„์›Œํฌ
  • ๋™์‹œ์„ฑ ์ปฌ๋ ‰์…˜
    • List, Queue, Map ๊ฐ™์€ ํ‘œ์ค€ ์ปฌ๋ ‰์…˜ ์ธํ„ฐํŽ˜์ด์Šค์— ๋™์‹œ์„ฑ์„ ๊ฐ€๋ฏธํ•ด ๊ตฌํ˜„ํ•œ ๊ณ ์„ฑ๋Šฅ ์ปฌ๋ ‰์…˜
      • ๋†’์€ ๋™์‹œ์„ฑ์„ ์œ„ํ•ด ๋™๊ธฐํ™”๋ฅผ ๋‚ด๋ถ€์—์„œ ์ˆ˜ํ–‰ (๋™์‹œ์„ฑ ๋ฌด๋ ฅํ™” ๋ถˆ๊ฐ€, ์™ธ๋ถ€์— ๋ฝ์‹œ ๋” ๋Š๋ ค์ง)
    • ConcurrentHashMap์€ synchronizedMap๋ณด๋‹ค ํ›จ์”ฌ ์ข‹๋‹ค.
      • ๋™์‹œ์„ฑ ๋งต์€ ๋™๊ธฐํ™”๋œ ๋งต์— ๋น„ํ•ด ์„ฑ๋Šฅ์ด ํ›จ์”ฌ ์ข‹๋‹ค.
  • ๋™๊ธฐํ™” ์žฅ์น˜ (synchronizer)
  • ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ์„ ์žด ๋•Œ๋Š” ํ•ญ์ƒ System.currentTimeMillis๊ฐ€ ์•„๋‹Œ System.nanoTime์„ ์‚ฌ์šฉํ•˜์ž
  • wait๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ wait loop ๊ด€์šฉ๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ผ. ๋ฐ˜๋ณต๋ฌธ ๋ฐ–์—์„œ๋Š” ์ ˆ๋Œ€๋กœ ํ˜ธ์ถœํ•˜์ง€ ๋ง์ž

wait์™€ notify๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜๋Š” ๊ฑด ๋™์‹œ์„ฑ ‘์–ด์…ˆ๋ธ”๋ฆฌ ์–ธ์–ด'๋กœ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ•˜๋Š” ๊ฒƒ์— ๋น„์œ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฐ˜๋ฉด java.util.concurrent๋Š” ๊ณ ์ˆ˜์ค€ ์–ธ์–ด์— ๋น„์œ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ฝ”๋“œ๋ฅผ ์ƒˆ๋กœ ์ž‘์„ฑํ•œ๋‹ค๋ฉด ์ด๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์ „ํ˜€ ์—†๋Š” ๊ฒƒ์ด๋‹ค.

์•„์ดํ…œ 82 : ์Šค๋ ˆ๋“œ ์•ˆ์ •์„ฑ ์ˆ˜์ค€์„ ๋ฌธ์„œํ™”ํ•˜๋ผ

๋ฉ”์„œ๋“œ ์„ ์–ธ์— synchronized ํ•œ์ •์ž๋ฅผ ์„ ์–ธํ• ์ง€๋Š” ๊ตฌํ˜„ ์ด์Šˆ์ผ ๋ฟ API์— ์†ํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ฆ‰, ์ด๊ฒƒ๋งŒ์œผ๋กœ๋Š” ์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•˜๋‹ค๊ณ  ํ™•์‹ ํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

  • ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ๋„ API๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ํด๋ž˜์Šค๊ฐ€ ์ง€์›ํ•˜๋Š” ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ ์ˆ˜์ค€์„ ์ •ํ™•ํžˆ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค.
    1. ๋ถˆ๋ณ€(immutable) : ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋Š” ์ƒ์ˆ˜์™€ ๊ฐ™์•„์„œ ์™ธ๋ถ€ ๋™๊ธฐํ™”๋„ ํ•„์š” ์—†๋‹ค.
    2. ๋ฌด์กฐ๊ฑด์  ์Šค๋ ˆ๋“œ ์•ˆ์ „(unconditionally thread-safe) : ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋Š” ์ˆ˜์ •๋  ์ˆ˜ ์žˆ์œผ๋‚˜, ๋ณ„๋„์˜ ์™ธ๋ถ€ ๋™๊ธฐํ™” ์—†์ด ๋™์‹œ ์‚ฌ์šฉํ•ด๋„ ์•ˆ์ „ํ•˜๋‹ค
    3. ์กฐ๊ฑด๋ถ€ ์Šค๋ ˆ๋“œ ์•ˆ์ „(conditionally thread-safe) : ๋ฌด์กฐ๊ฑด์  ์Šค๋ ˆ๋“œ ์•ˆ์ „๊ณผ ๊ฐ™์œผ๋‚˜, ์ผ๋ถ€ ๋ฉ”์„œ๋“œ๋Š” ๋™์‹œ์— ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์™ธ๋ถ€ ๋™๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
    4. ์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•˜์ง€ ์•Š์Œ(not thread-safe) : ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋Š” ์ˆ˜์ •๋  ์ˆ˜ ์žˆ๋‹ค. ๋™์‹œ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋™๊ธฐํ™”ํ•ด์•ผ ํ•œ๋‹ค.
    5. ์Šค๋ ˆ๋“œ ์ ๋Œ€์ (thread-hostile) : ๋ชจ๋“  ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ์™ธ๋ถ€ ๋™๊ธฐํ™”ํ•˜๋”๋ผ๋„ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์•ˆ์ „ํ•˜์ง€ ์•Š๋‹ค.

์ •ํ™•ํ•œ ์–ธ์–ด๋กœ ์„ค๋ช…ํ•˜๊ฑฐ๋‚˜ ์Šค๋ ˆ๋“œ ์•ˆ์ •์„ฑ ์• ๋„ˆํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ํด๋ž˜์Šค์˜ ์Šค๋ ˆ๋“œ ์•ˆ์ •์„ฑ์€ ๋ณดํ†ต ํด๋ž˜์Šค์˜ ๋ฌธ์„œํ™” ์ฃผ์„์— ๊ธฐ์žฌํ•œ๋‹ค. ๋…ํŠนํ•œ ํŠน์„ฑ์„ ๊ฐ€์ง„ ๋ฉ”์„œ๋“œ๋ผ๋ฉด ํ•ด๋‹น ๋ฉ”์„œ๋“œ์˜ ์ฃผ์„์— ๊ธฐ์žฌํ•˜๋„๋ก ํ•œ๋‹ค.

์•„์ดํ…œ 83 : ์ง€์—ฐ ์ดˆ๊ธฐํ™”๋Š” ์‹ ์ค‘ํžˆ ์‚ฌ์šฉํ•˜๋ผ

์ง€์—ฐ์ดˆ๊ธฐํ™”๋ž€ ํ•„๋“œ์˜ ์ดˆ๊ธฐํ™” ์‹œ์ ์„ ๊ทธ๋ฐง์ด ์ฒ˜์Œ ํ•„์š”ํ•  ๋•Œ๊นŒ์ง€ ๋Šฆ์ถ”๋Š” ๊ธฐ๋ฒ•์ด๋‹ค. (์Šคํ”„๋ง ์ˆœํ™˜ ์ฐธ์กฐ ํ•ด๊ฒฐ ์‹œ ์‚ฌ์šฉํ–ˆ๋˜ ๊ธฐ์–ต์ด ๋‚œ๋‹ค)

  • ์ฃผ๋กœ ์ตœ์ ํ™” ์šฉ๋„์— ์‚ฌ์šฉํ•˜๋ฉฐ ํด๋ž˜์Šค์™€ ์ธ์Šคํ„ด์Šค ์ดˆ๊ธฐํ™” ์‹œ ๋ฐœ์ƒํ•˜๋Š” ์ˆœํ™˜ ๋ฌธ์ œ ํ•ด๊ฒฐ ์‹œ์—๋„ ์‚ฌ์šฉ

์„ฑ๋Šฅ์ ์œผ๋กœ ์ง€์—ฐ์ดˆ๊ธฐํ™”๊ฐ€ ์ข‹์€ ๊ฒฝ์šฐ๋Š” ํ•ด๋‹น ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค ์ค‘ ๊ทธ ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ ๋‚ฎ์œผ๋ฉด์„œ ๊ทธ ํ•„๋“œ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋น„์šฉ์ด ํฐ ๊ฒฝ์šฐ์ด๋‹ค.

ํ•˜์ง€๋งŒ, ์ด๋Ÿฐ ๊ฒฝ์šฐ๊ฐ€ ์ ๊ณ  ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์— ์ ์šฉํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต๋‹ค. ๋”ฐ๋ผ์„œ ๋Œ€๋ถ€๋ถ„์˜ ์ƒํ™ฉ์—์„œ ์ผ๋ฐ˜์ ์ธ ์ดˆ๊ธฐํ™”๊ฐ€ ์ง€์—ฐ ์ดˆ๊ธฐํ™”๋ณด๋‹ค ๋‚ซ๋‹ค

  • ์ง€์—ฐ์ดˆ๊ธฐํ™” ๋ฐฉ๋ฒ•
    • ์ง€์—ฐ์ดˆ๊ธฐํ™”๊ฐ€ ์ดˆ๊ธฐํ™” ์ˆœํ™˜์„ฑ์„ ๊นจ๋œจ๋ฆด ๊ฒƒ ๊ฐ™์œผ๋ฉด synchronized ์ ‘๊ทผ์ž๋ฅผ ์‚ฌ์šฉํ•˜์ž
    • ์„ฑ๋Šฅ ๋•Œ๋ฌธ์— ์ •์  ํ•„๋“œ๋ฅผ ์ง€์—ฐ ์ดˆ๊ธฐํ™”ํ•ด์•ผ ํ•œ๋‹ค๋ฉด lazy initialization holder class ๊ด€์šฉ๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์ž
    • ๋Šฅ ๋•Œ๋ฌธ์— ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋ฅผ ์ง€์—ฐ ์ดˆ๊ธฐํ™”ํ•ด์•ผ ํ•œ๋‹ค๋ฉด double-check ๊ด€์šฉ๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ผ

๋Œ€๋ถ€๋ถ„์€ ์ง€์—ฐ ์ดˆ๊ธฐํ™”๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์ง€๋งŒ ๊ผญ ํ•„์š”ํ•˜๋‹ค๋ฉด ์˜ฌ๋ฐ”๋ฅธ ์ง€์—ฐ์ดˆ๊ธฐํ™” ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•˜์ž.

์•„์ดํ…œ 84 : ํ”„๋กœ๊ทธ๋žจ์˜ ๋™์ž‘์„ ์Šค๋ ˆ๋“œ ์Šค์ผ€์ค„๋Ÿฌ์— ๊ธฐ๋Œ€์ง€ ๋ง๋ผ

์ž˜ ์ž‘์„ฑ๋œ ํ”„๋กœ๊ทธ๋žจ์€ ์Šค๋ ˆ๋“œ ์Šค์ผ€์ค„๋Ÿฌ์— ๋”ฐ๋ผ ์„ฑ๋Šฅ์ด ์š”๋™์ณ์„œ๋Š” ์•ˆ๋œ๋‹ค.

์ •ํ™•์„ฑ์ด๋‚˜ ์„ฑ๋Šฅ์ด ์Šค๋ ˆ๋“œ ์Šค์ผ€์ค„๋Ÿฌ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋Š” ํ”„๋กœ๊ทธ๋žจ์ด๋ผ๋ฉด ๋‹ค๋ฅธ ํ”Œ๋žซํผ์— ์ด์‹ํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

์Šค๋ ˆ๋“œ ์ˆ˜๊ฐ€ ์ง€๋‚˜์น˜๊ฒŒ ๋งŽ๋‹ค๋ฉด ์Šค์ผ€์ค„๋Ÿฌ์˜ ๊ณ ๋ฏผ๊ฑฐ๋ฆฌ๊ฐ€ ๋Š˜์–ด๋‚˜๊ณ  ์ด๋Š” ์ •์ฑ…์— ๋”ฐ๋ผ ์„ฑ๋Šฅ์ด ๋‹ฌ๋ผ์ง€๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์Šค๋ ˆ๋“œ ์ˆ˜๋ฅผ ์ ๊ฒŒ ์œ ์ง€ํ•˜๋Š” ๊ธฐ๋ฒ•์€ ๊ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ์ž‘์—…์„ ์™„๋ฃŒํ•œ ํ›„ ๋‹ค์Œ ์ผ๊ฑฐ๋ฆฌ๊ฐ€ ์ƒ๊ธธ ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์Šค๋ ˆ๋“œ๋Š” ๋‹น์žฅ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ์ž‘์—…์ด ์—†๋‹ค๋ฉด ์‹คํ–‰๋ผ์„œ๋Š” ์•ˆ๋œ๋‹ค.

  • ์Šค๋ ˆ๋“œ ํ’€ ํฌ๊ธฐ๋ฅผ ์ ์ ˆํžˆ ์„ค์ •ํ•˜๊ณ  ์ž‘์—…์€ ์งง๊ฒŒ ์œ ์ง€ํ•˜์ž

์Šค๋ ˆ๋“œ๋Š” ์ ˆ๋Œ€ ๋ฐ”์œ ๋Œ€๊ธฐ ์ƒํƒœ๊ฐ€ ๋˜๋ฉด ์•ˆ๋œ๋‹ค.

  • ์Šค๋ ˆ๋“œ ์Šค์ผ€์ค„๋Ÿฌ์˜ ๋ณ€๋•์— ์ทจ์•ฝํ•˜๊ณ , ํ”„๋กœ์„ธ์„œ์— ํฐ ๋ถ€๋‹ด์„ ์ค€๋‹ค.

ํŠน์ • ์Šค๋ ˆ๋“œ๊ฐ€ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋“ค๊ณผ ๋น„๊ตํ•ด CPU ์‹œ๊ฐ„์„ ์ถฉ๋ถ„ํžˆ ์–ป์ง€ ๋ชปํ•ด์„œ ๊ฐ„์‹ ํžˆ ๋Œ์–ด๊ฐ€๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๋ณด๋”๋ผ๋„ Thread.yield๋ฅผ ์จ์„œ ๋ฌธ์ œ๋ฅผ ๊ณ ์ณ๋ณด๋ ค๋Š” ์œ ํ˜น์„ ๋–จ์ณ๋‚ด์ž

  • ํ…Œ์ŠคํŠธํ•  ์ˆ˜๋‹จ๋„ ์—†๊ณ , ์ด์‹์„ฑ๋„ ๋‚ฎ๋‹ค.