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

๐Ÿ’ป Computer Science/Operating System

๐Ÿคฟ Deep dive: Java ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ํ•ด์•ผํ•  ๊ฒƒ์€ ๋ฌด์—‡์ธ๊ฐ€?

Intro

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

 

๋˜ํ•œ, ๋ฐ์ดํ„ฐ์˜ ๊ฐ€๋ณ€์„ฑ(Mutability)์€ ์ค‘์š”ํ•˜๋‹ค. ํ”„๋กœ๊ทธ๋žจ์ด ๋™์ž‘ํ•˜๋ฉด์„œ ์ƒํ™ฉ์— ๋”ฐ๋ผ ์ƒํƒœ๊ฐ€ ๋ณ€ํ™”ํ•˜๋Š”๊ฒŒ ์ผ๋ฐ˜์ ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

ํ•˜์ง€๋งŒ! ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ ํ™˜๊ฒฝ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ๋ฅผ ์ƒ๊ฐํ•ด๋ณด์ž.

๋งŒ์•ฝ ์–ด๋–ค ๋ณ€์ˆ˜ a์˜ ๊ฐ’์„ Thread-1, Thread-2๊ฐ€ ๋™์‹œ์— ๋ณ€๊ฒฝํ•œ๋‹ค๋ฉด?

์„œ๋กœ ๋‹ค๋ฅธ ์‹œ์ ์— ์ฝ์–ด์„œ ๋ณ€๊ฒฝํ•˜๊ณ  ์ผ๋Š”๋ฐ, ๊ทธ ๊ฐ’์ด ๋ฎ์–ด์“ฐ์—ฌ์ง„๋‹ค๋ฉด?

๋ฏฟ์„ ์ˆ˜ ์—†๋Š” ๋ฐ์ดํ„ฐ๋ฐ–์— ๋‚จ์ง€ ์•Š๊ฒŒ ๋˜๊ฒ ์ง€....

 

๊ทธ๋Ÿผ ์ด์ œ ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ(Thread safety)์ด๋ผ๋Š” ์šฉ์–ด์˜ ์˜๋ฏธ๋ถ€ํ„ฐ ์•Œ์•„๋ณด์ž.

์ด ๋ง์€ "์Šค๋ ˆ๋“œ๊ฐ€ ์•ˆ์ „ํ•˜๋‹ค" ๋ผ๋Š” ๋œป์ด ์•„๋‹ˆ๋ผ, "์Šค๋ ˆ๋“œ์˜ ๋™์ž‘์œผ๋กœ๋ถ€ํ„ฐ ํ”„๋กœ๊ทธ๋žจ์ด ์•ˆ์ „ํ•˜๋‹ค"๋ผ๋Š” ๋œป์ด๋‹ค.

ํ’€์–ด์„œ ์„ค๋ช…ํ•˜์ž๋ฉด, ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ์ปดํ“จํ„ฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ™˜๊ฒฝ์—์„œ ๋™์ž‘ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ์˜ˆ๊ธฐ์น˜ ๋ชปํ•œ ๋™์ž‘์ด๋‚˜ ๊ฒฝ์Ÿ ์กฐ๊ฑด, ๋ฐ์ดํ„ฐ ์†์ƒ ์—†์ด ์ •์ƒ์ ์œผ๋กœ ์ž‘์—…์ด ์ง„ํ–‰๋˜๊ณ  ์žˆ์„ ๋•Œ Thread-safe ํ•˜๋‹ค ๋ผ๊ณ  ํ‘œํ˜„ํ•œ๋‹ค.

 

 

์ง€๊ธˆ๋ถ€ํ„ฐ, Java ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ธฐ์ค€์œผ๋กœ ์–ด๋–ป๊ฒŒ ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๋Š”์ง€์— ๋Œ€ํ•ด ์ตœ๋Œ€ํ•œ ๊นŠ๊ณ  ์ž์„ธํžˆ ์•Œ์•„๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

โ“๊ฒฝ์Ÿ ์กฐ๊ฑด์ด๋ž€?
2๊ฐœ ์ด์ƒ์˜ ํ”„๋กœ์„ธ์Šค๋‚˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ณต์œ  ์ž์›(๋ณ€์ˆ˜, ๋ฉ”๋ชจ๋ฆฌ ๋“ฑ)์— ๋™์‹œ์— ์ ‘๊ทผํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ฑฐ๋‚˜ ์“ธ ๋•Œ, ์ ‘๊ทผํ•˜๋Š” ์ˆœ์„œ์— ๋”ฐ๋ผ ์‹คํ–‰ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ฌ๋ผ์ง€๋Š” ์ƒํ™ฉ์„ ๋งํ•œ๋‹ค.
์ด๋Ÿฌํ•œ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•˜๋ฉด ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋Š”, ์ž˜๋ชป๋œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ฌ ์œ„ํ—˜์ด ์žˆ์–ด ๋™๊ธฐํ™” ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํ†ตํ•ด ํ•ด๊ฒฐํ•ด์•ผ ํ•œ๋‹ค.
๐Ÿ‘‰ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ง€๋‚œ ํฌ์ŠคํŒ… ์ฐธ๊ณ 

์Šค๋ ˆ๋“œ ์•ˆ์ „์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•

ํ”„๋กœ๊ทธ๋žจ์˜ ๊ทœ๋ชจ๊ฐ€ ์ปค์งˆ ์ˆ˜๋ก ํŠน์ • ๋ณ€์ˆ˜๊ฐ€ ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ์—์„œ ์ ‘๊ทผ๋˜๊ณ  ์žˆ๋Š”์ง€ ํŒŒ์•…ํ•˜๋Š” ๊ฒƒ์กฐ์ฐจ ๊ฐ„๋‹จํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค.

๋’ค๋Šฆ๊ฒŒ ๊ณ ์น˜๊ธฐ๋ž€ ์‰ฝ์ง€ ์•Š์œผ๋‹ˆ ... ๋”ฐ๋ผ์„œ ์ดˆ๊ธฐ ์„ค๊ณ„ ์‹œ์ ๋ถ€ํ„ฐ ์˜์‹์ ์œผ๋กœ ์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•˜๊ฒŒ ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ์ด ์ •๋ง ์ค‘์š”ํ•˜๋‹ค!

 

์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”, ๊ฒฝ์Ÿ ์กฐ๊ฑด์ด ๋ฐœ์ƒํ•˜๋ฉด ์•ˆ๋œ๋‹ค.

๊ฒฝ์Ÿ ์กฐ๊ฑด์„ ํ”ผํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๊ด€์ ์— ๋”ฐ๋ผ ๋‘ ๊ฐ€์ง€๋กœ ๋‚˜๋ˆ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

1. ๊ณต์œ  ์ƒํƒœ ํ”ผํ•˜๊ธฐ

์ผ๋‹จ ๊ณต์œ  ์ƒํƒœ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ตœ๋Œ€ํ•œ ํ”ผํ•˜์ž๋Š” ๊ฒƒ์ด๋‹ค.

์Šค๋ ˆ๋“œ ๊ฐ„์— ๊ณต์œ ๋˜๋Š” ์ž์›์„ ์ตœ์†Œํ™”ํ•˜๊ณ , ์ •๋ง ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ๋™๊ธฐํ™”๋ฅผ ์ ์šฉํ•ด์•ผ ํ•œ๋‹ค.

๊ตฌ์ฒด์ ์œผ๋กœ ์–ด๋–ค ๋ฐฉ๋ฒ•๋“ค์ด ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด์ž.

 

1) ์ƒํƒœ ์ •๋ณด๋ฅผ ์ •์  ๋ณ€์ˆ˜ ๋Œ€์‹  ์ง€์—ญ ๋ณ€์ˆ˜์— ์ €์žฅํ•œ๋‹ค.

์Šค๋ ˆ๋“œ๋Š” ๊ฐ๊ฐ ๋ณ„๋„์˜ ์Šคํƒ ์˜์—ญ์„ ๊ฐ€์ง€๋ฉฐ, ์ง€์—ญ ๋ณ€์ˆ˜๋Š” ์ด ๊ณต๊ฐ„์— ์ €์žฅ๋œ๋‹ค.

๋”ฐ๋ผ์„œ, ์ง€์—ญ ๋ณ€์ˆ˜๋กœ ์„ ์–ธ๋œ ๊ฒฝ์šฐ ํ•ด๋‹น ๋ณ€์ˆ˜๋Š” ์Šค๋ ˆ๋“œ๋งˆ๋‹ค ๋…๋ฆฝ์ ์ธ ๋ณต์‚ฌ๋ณธ์„ ๊ฐ€์ง€๊ฒŒ ๋˜์–ด ์Šค๋ ˆ๋“œ ๊ฐ„์— ๊ณต์œ ๋˜์ง€ ์•Š๋Š”๋‹ค. ์ด์— ๋”ฐ๋ผ ๊ฒฝ์Ÿ ์กฐ๊ฑด์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์Šค๋ ˆ๋“œ ์•ˆ์ „์ด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ™•๋ณด๋œ๋‹ค.

 

2) ThreadLocal ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

ThreadLocal์€ ๊ฐ ์Šค๋ ˆ๋“œ๋งˆ๋‹ค ๋…๋ฆฝ์ ์ธ ๋ณ€์ˆ˜๋ฅผ ์ €์žฅ·๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ž๋ฐ”์—์„œ ์ œ๊ณตํ•˜๋Š” ํด๋ž˜์Šค์ด๋‹ค. ์ผ๋ฐ˜ ์ง€์—ญ ๋ณ€์ˆ˜๋Š” ์„ ์–ธ๋œ ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด ํ™œ์šฉํ•  ์ˆ˜ ์—†์ง€๋งŒ, ThreadLocal์„ ์‚ฌ์šฉํ•˜๋ฉด ํŠน์ • ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰ํ•˜๋Š” ๋ชจ๋“  ์ฝ”๋“œ ๋ฒ”์œ„์—์„œ ๋™์ผํ•œ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.

 

Thread ๋‚ด๋ถ€์—๋Š” ๊ฐ ์Šค๋ ˆ๋“œ๋ณ„๋กœ ํ•˜๋‚˜์”ฉ ThreadLocalMap ์ธ์Šคํ„ด์Šค๊ฐ€ ์กด์žฌํ•œ๋‹ค. ์ด ThreadLocalMap์€ ํ•ด๋‹น ์Šค๋ ˆ๋“œ์˜ ์ €์žฅ์†Œ ์—ญํ• ์„ ํ•˜๋ฉฐ, ์—ฌ๊ธฐ์—์„œ ThreadLocal ๊ฐ์ฒด๊ฐ€ ํ‚ค(key)๋กœ ์‚ฌ์šฉ๋˜๊ณ , ๊ทธ์— ๋Œ€์‘ํ•˜๋Š” ๊ฐ’์ด ์ €์žฅ๋œ๋‹ค.

 

์ฆ‰, ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ํ•˜๋‚˜์˜ ThreadLocal ๊ฐ์ฒด๋ฅผ ๊ณต์œ ํ•˜๋”๋ผ๋„, ์‹ค์ œ ์ €์žฅ๋˜๋Š” ๊ฐ’์€ ๊ฐ ์Šค๋ ˆ๋“œ ๊ฐ„์— ๋ณ„๋„๋กœ ๋ถ„๋ฆฌ๋˜์–ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋กœ ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋Ÿฐ ๊ตฌ์กฐ ๋•๋ถ„์— ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ๋„ ๋™๊ธฐํ™” ์—†์ด ์•ˆ์ „ํ•˜๊ฒŒ ๊ฐ ์Šค๋ ˆ๋“œ๋งŒ์˜ ๋…๋ฆฝ์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

 

3) Immutable objct๋ฅผ ํ™œ์šฉํ•œ๋‹ค.

mutable์€ '๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋Š”'์ด๋ผ๋Š” ๋œป์ด๊ณ , ๋ฐ˜๋Œ€๋กœ Immutability๋Š” '๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅ์„ฑ'์„ ์˜๋ฏธํ•œ๋‹ค. 

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ๋ถˆ๋ณ€ ๊ฐ์ฒด(Immutable Object)๋Š” ๋™๊ธฐํ™” ์—†์ด๋„ ์•ˆ์ „ํ•˜๊ฒŒ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์–ด ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ณด์žฅํ•œ๋‹ค. 

Java์—์„œ๋Š” ์ƒ์„ฑ ์ดํ›„ ๋ณ€๊ฒฝ๋  ํ•„์š”๊ฐ€ ์—†๋Š” ๋ณ€์ˆ˜์— final ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์—ฌ ๋ณ€๊ฒฝ์„ ๊ธˆ์ง€ํ•œ๋‹ค. final ํ•„๋“œ๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ์ดˆ๊ธฐํ™” ์ดํ›„ ๊ฐ’์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†์œผ๋ฉฐ, ์ด๋กœ ์ธํ•ด ๊ฐ’ ์ผ๊ด€์„ฑ์ด ๋ณด์žฅ๋˜์–ด ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ ‘๊ทผํ•ด๋„ ์•ˆ์ „ํ•˜๋‹ค.

Java์˜ String, ๋ž˜ํผ ํด๋ž˜์Šค ๋“ฑ์ด ์ข‹์€ ์˜ˆ์‹œ์ด๋‹ค.


2. ๊ณต์œ  ์ƒํƒœ๋ฅผ ํ”ผํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, ๋™๊ธฐํ™” ๋ฉ”์ปค๋‹ˆ์ฆ˜ ํ™œ์šฉํ•˜๊ธฐ

ํ•˜์ง€๋งŒ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ”„๋กœ๊ทธ๋žจ์—์„œ๋Š” ๊ณต์œ  ์ƒํƒœ๊ฐ€ ๋ถˆ๊ฐ€ํ”ผํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค. ์ด ๊ฒฝ์šฐ์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์Šค๋ ˆ๋“œ ์•ˆ์ „ ๋ณด์žฅ์„ ์œ„ํ•œ ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋ฒ•๋“ค์„ ์•Œ์•„๋ณด์ž.

 

1) ์›์ž์  ์—ฐ์‚ฐ(Atomic operations)

์ด ๋ฐฉ๋ฒ•์€ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ์ค‘๋‹จํ•  ์ˆ˜ ์—†๋Š” ์›์ž์ ์ธ ์—ฐ์‚ฐ์„ ํ†ตํ•ด์„œ๋งŒ ๊ณต์œ  ์ž์›์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์—ฐ์‚ฐ ์ž์ฒด๊ฐ€ ์›์ž์ ์œผ๋กœ ์ˆ˜ํ–‰๋˜๋ฏ€๋กœ, ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ์–ธ์ œ ์–ด๋–ป๊ฒŒ ์•ก์„ธ์Šคํ•˜๋Š”์ง€์™€ ์ƒ๊ด€์—†์ด ๊ณต์œ  ๋ฐ์ดํ„ฐ๊ฐ€ ํ•ญ์ƒ ์œ ํšจํ•œ ์ƒํƒœ๋กœ ์œ ์ง€๋  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋Ÿฌํ•œ ์›์ž์  ์—ฐ์‚ฐ์€ ๋งŽ์€ ์Šค๋ ˆ๋“œ Lock ๋ฉ”์ปค๋‹ˆ์ฆ˜์˜ ๊ธฐ๋ณธ ์›๋ฆฌ์ด๋‹ค.

 

Atomic ํด๋ž˜์Šค ํ™œ์šฉ

Java๋Š” java.util.concurrent.atomic ํŒจํ‚ค์ง€์—์„œ ๋‹ค์–‘ํ•œ Atomic ํด๋ž˜์Šค๋“ค์„ ์ œ๊ณตํ•œ๋‹ค. 

๋Œ€ํ‘œ์ ์œผ๋กœ AtomicInteger, AtomicLong, AtomicBoolean, AtomicReference ๋“ฑ์ด ์žˆ๋‹ค. 

์ด๋“ค์€ ๋‚ด๋ถ€์ ์œผ๋กœ ํ•˜๋“œ์›จ์–ด ์ˆ˜์ค€์˜ ์›์ž์  ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฝ ์—†์ด ์•ˆ์ „ํ•œ ์—ฐ์‚ฐ์„ ๋ณด์žฅํ•œ๋‹ค. 

 

์ฃผ์š” ๋ฉ”์„œ๋“œ:

get(): ํ˜„์žฌ ๊ฐ’์„ ๋ฐ˜ํ™˜

set(newValue): ๊ฐ’์„ ์„ค์ •

getAndIncrement(), incrementAndGet(): ๊ฐ’์„ ์›์ž์ ์œผ๋กœ 1 ์ฆ๊ฐ€

compareAndSet(expectedValue, newValue): ๊ธฐ๋Œ€๊ฐ’๊ณผ ์‹ค์ œ ๊ฐ’์ด ์ผ์น˜ํ•˜๋ฉด ์ƒˆ ๊ฐ’์œผ๋กœ ์›์ž์  ๊ต์ฒด

 

์‚ฌ์šฉ ์˜ˆ์‹œ:

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicExample {
    private AtomicInteger counter = new AtomicInteger(0);

    public void increment() {
        counter.incrementAndGet();
    }

    public int getCounter() {
        return counter.get();
    }
}

 

2) ์ƒํ˜ธ ๋ฐฐ์ œ(Mutual exclution) ๋ฐ synchronized ํ‚ค์›Œ๋“œ ํ™œ์šฉ

์ด ๋ฐฉ๋ฒ•์€ ๊ณต์œ  ์ž์›์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๋ฅผ ํ•ญ์ƒ ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•˜๋Š” ๋งค์ปค๋‹ˆ์ฆ˜์ด๋‹ค.

ํ•ญ์ƒ ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ๊ณต์œ  ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ฑฐ๋‚˜ ์“ธ ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

์ด ๋งค์ปค๋‹ˆ์ฆ˜์„ ๋ถ€์ ์ ˆํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด,  deadlocks, livelocks,  resource starvation๊ณผ ๊ฐ™์€ ๋ถ€์ž‘์šฉ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.


์ž๋ฐ”์—์„œ๋Š” synchronized ํ‚ค์›Œ๋“œ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ž„๊ณ„์˜์—ญ์„ ๋ณดํ˜ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋Š” ํ•œ ์‹œ์ ์— ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ๊ณต์œ  ์ž์›์— ์ ‘๊ทผํ•˜๋„๋ก ๋ณด์žฅํ•˜์—ฌ ๊ฒฝ์Ÿ ์กฐ๊ฑด์„ ๋ฐฉ์ง€ํ•œ๋‹ค.

๋ฉ”์„œ๋“œ๋‚˜ ์ฝ”๋“œ ๋ธ”๋ก์— ์ ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ๋ฝ์ด ๊ฑธ๋ฆฐ ๋™์•ˆ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋Š” ๋Œ€๊ธฐํ•˜๊ฒŒ ๋œ๋‹ค.

 

๋‹ค์Œ ์˜ˆ์‹œ ๋ฉ”์„œ๋“œ inc()๋Š” synchronized ํ‚ค์›Œ๋“œ ๋•๋ถ„์—, thread safeํ•˜๊ฒŒ ๋™์ž‘ํ•œ๋‹ค.

class Counter {
    private int i = 0;

    public synchronized void inc() {
        i++;
    }
}
โ“๊ต์ฐฉ ์ƒํƒœ(DeadLock)๋ž€?
๊ต์ฐฉ ์ƒํƒœ๋Š” ๋‘˜ ์ด์ƒ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ์„œ๋กœ ์ƒ๋Œ€๋ฐฉ์ด ์ ์œ ํ•œ ์ž์›์˜ ํ•ด์ œ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋А๋ผ ๋ฌดํ•œํžˆ ๋Œ€๊ธฐํ•˜๋ฉฐ ์ž‘์—…์„ ์ง„ํ–‰ํ•˜์ง€ ๋ชปํ•˜๋Š” ์ƒํƒœ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. 
์ฆ‰, ์Šค๋ ˆ๋“œ A๋Š” ์ž์› 1์„ ์ ์œ ํ•œ ์ฑ„ ์ž์› 2๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๊ณ , ๋™์‹œ์— ์Šค๋ ˆ๋“œ B๋Š” ์ž์› 2๋ฅผ ์ ์œ ํ•œ ์ฑ„ ์ž์› 1์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ƒํ™ฉ์ฒ˜๋Ÿผ ์„œ๋กœ๊ฐ€ ์„œ๋กœ์˜ ์ž์›์„ ๊ธฐ๋‹ค๋ฆฌ๋ฉด์„œ ์˜์›ํžˆ ๋Œ€๊ธฐ ์ƒํƒœ์— ๋น ์ง€๋Š” ํ˜„์ƒ์ด๋‹ค.
๊ต์ฐฉ ์ƒํƒœ๊ฐ€ ๋ฐœ์ƒํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋„ค ๊ฐ€์ง€ ์กฐ๊ฑด์ด ๋ชจ๋‘ ์„ฑ๋ฆฝํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์•Œ๋ ค์ ธ ์žˆ๋‹ค:
1. ์ƒํ˜ธ ๋ฐฐ์ œ(Mutual Exclusion): ์ž์›์€ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
2. ์ ์œ ์™€ ๋Œ€๊ธฐ(Hold and Wait): ์ž์›์„ ์ ์œ ํ•œ ์ƒํƒœ์—์„œ ์ถ”๊ฐ€ ์ž์›์„ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
3. ๋น„์„ ์ (No Preemption): ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ์ ์œ ํ•œ ์ž์›์„ ๊ฐ•์ œ๋กœ ๋นผ์•—์„ ์ˆ˜ ์—†๋‹ค.
4. ์ˆœํ™˜ ๋Œ€๊ธฐ(Circular Wait): ์Šค๋ ˆ๋“œ ์ง‘ํ•ฉ ๋‚ด์—์„œ ์„œ๋กœ๊ฐ€ ์ ์œ ํ•œ ์ž์›์„ ์ˆœํ™˜ ํ˜•ํƒœ๋กœ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
๊ต์ฐฉ ์ƒํƒœ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๊ด€๋ จ ์Šค๋ ˆ๋“œ๋“ค์ด ๋ฌดํ•œ ๋Œ€๊ธฐ ์ƒํƒœ์— ๋น ์ ธ ํ”„๋กœ๊ทธ๋žจ์ด ๋ฉˆ์ถ”๊ฑฐ๋‚˜ ์‘๋‹ตํ•˜์ง€ ์•Š๋Š” ๋“ฑ์˜ ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
โ“LiveLock์ด๋ž€?

โ“Starvation์ด๋ž€?

 

3) Lock ํ™œ์šฉ

๋” ์„ธ๋ฐ€ํ•œ ์ œ์–ด๊ฐ€ ํ•„์š”ํ•  ๋•Œ๋Š” java.util.concurrent.locks ํŒจํ‚ค์ง€์˜ ReentrantLock ๊ฐ™์€ ๋ฝ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. 

๋ฝ ํš๋“๊ณผ ํ•ด์ œ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด, ์กฐ๊ฑด๋ถ€ ๋ฝ์ด๋‚˜ ํƒ€์ž„์•„์›ƒ ๋ฝ ๊ตฌํ˜„์— ์šฉ์ดํ•˜๋‹ค.

๋ฝ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๊ด€๋ จํ•œ ์„ธ๋ถ€ ๋‚ด์šฉ์€ ๊ธฐ์กด ํฌ์ŠคํŒ…์„ ์ฐธ๊ณ ํ•˜์ž.


4) ๋™์‹œ์„ฑ ๋ฌธ์ œ๊ฐ€ ์—†๋Š” ์ž๋ฃŒ๊ตฌ์กฐ ํ™œ์šฉ

java.util.concurrent ํŒจํ‚ค์ง€์— ์กด์žฌํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๋“ค์ด๋‹ค.

๋Œ€ํ‘œ์ ์œผ๋กœ ConcurrentHashMap, BlockingQueue ๋“ฑ์ด ์žˆ๋‹ค.

์ถ”๊ฐ€ ๋‚ด์šฉ

volatile ํ‚ค์›Œ๋“œ ํ™œ์šฉ

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

์ด๋Ÿฌํ•œ ์ƒํ™ฉ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด volatile ํ‚ค์›Œ๋“œ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. 

volatile ํ‚ค์›Œ๋“œ๋Š” ์ž๋ฐ”์—์„œ ๋ณ€์ˆ˜ ์ ‘๊ทผ ์‹œ ๋ฉ”์ธ ๋ฉ”๋ชจ๋ฆฌ์˜ ์ตœ์‹  ๊ฐ’์„ ์ฝ๊ณ  ์“ฐ๋„๋ก ๋ณด์žฅํ•œ๋‹ค.
์ฆ‰, volatile ํ‚ค์›Œ๋“œ๋Š” ๋ณ€์ˆ˜์˜ ๊ฐ€์‹œ์„ฑ(visibility)์„ ๋ณด์žฅํ•˜์—ฌ ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ๋ณ€์ˆ˜์˜ ์ตœ์‹  ๊ฐ’์„ ์ฝ๋„๋ก ํ•˜์ง€๋งŒ, i++ ๊ฐ™์€ ๋ณตํ•ฉ ์—ฐ์‚ฐ(์ฝ๊ธฐ → ์—ฐ์‚ฐ → ์“ฐ๊ธฐ)์„ ์›์ž์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์ง€๋Š” ๋ชปํ•œ๋‹ค

๋”ฐ๋ผ์„œ ๋ณตํ•ฉ ์—ฐ์‚ฐ์— ๋Œ€ํ•ด์„  synchronized, Lock, Atomic ํด๋ž˜์Šค ๋“ฑ ๋™๊ธฐํ™” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‚˜ ์›์ž์  ์—ฐ์‚ฐ์„ ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

public class SharedObject {
    public volatile int counter = 0;
}
โ“๊ฐ€์‹œ์„ฑ ๋ฌธ์ œ๋ž€?
๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ณ€๊ฒฝํ•œ ๊ณต์œ  ๋ณ€์ˆ˜์˜ ์ตœ์‹  ์ƒํƒœ๋ฅผ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ ์ฆ‰์‹œ ํ™•์ธํ•  ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ

์ถ”๊ฐ€ ์กฐ์‚ฌ/ํ™•์ธํ•  ์ 

  • 4)์™€ 1) ์˜ Atomic ์ž๋ฃŒ๊ตฌ์กฐ์™€ ๋™๊ธฐํ™” ๋ฐฉ์‹์ด ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ์ง€. 
  • 4) ์ข€๋” ์ž์„ธํžˆ
  • ๋ฐฉ์‹ ๊ตฌ๋ถ„์ด ์ ์ ˆํ•œ์ง€
  • ๊ฐ ๋ฐฉ์‹์˜ ์žฅ๋‹จ์ 

์ฐธ๊ณ  ์ž๋ฃŒ