๊ฐ์
๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ๊ณต์ ์์์ ์ฌ์ฉํ ๋, ์ฃผ๋ก ์์์ฑ๊ณผ ๊ฐ์์ฑ์ด ์ธ๊ธ๋๋๋ฐ ์์์ฑ์ ๋ํด ์์ ๋ณด์!
์์์ฑ์ด๋
์์์ฑ์ ์ํค๋ฐฑ๊ณผ์ ๋ฐ๋ฅด๋ฉด ์ด๋ค ๊ฒ์ด ๋ ์ด์ ์ชผ๊ฐ์ง ์ ์๋ ์ฑ์ง์ ๋งํ๋ฉฐ, ์ด๋ค ๊ฒ์ด ์์์ฑ์ ๊ฐ์ง๊ณ ์๋ค๋ฉด ์์์ (Atomic) ์ด๋ผ๊ณ ํํํ๋ค.
์์์ฑ์ ์ฑ์ง์ ์ปดํจํฐ๊ณผํ์ ๋์ ํด๋ณด๋ฉด ์ด๋ ํ ์์ ์ด ์คํ๋ ๋, ์ธ์ ๋ ์์ ํ๊ฒ ์งํ๋์ด ์ข ๋ฃ๋๊ฑฐ๋ ๊ทธ๋ด ์ ์๋ ๊ฒฝ์ฐ ์คํ์ ํ์ง ์๋ ๊ฒฝ์ฐ๋ฅผ ๋งํ๋ค.
๋ฐ๋ผ์, ์์์ฑ์ ๊ฐ์ง๋ ์์ ์ ์คํ๋์ด ์งํ๋๋ค๊ฐ ์ข ๋ฃ๋์ง ์๊ณ ์ค๊ฐ์์ ๋ฉ์ถ๋ ๊ฒฝ์ฐ๋ ์ ๋๋ก ์์ ์ ์๋ค.
๊ฐ๋จํ ์์๋ฅผ ๋ค์ด๋ณด๋ฉด ๊ธฐ๊ณ์ด ์์ค์ ์คํ ๋ช ๋ น์ด๋ค์ ๊ฐ๊ฐ ์์์ฑ์ ๊ฐ์ง๊ณ ์๊ธฐ์ ADD์ LOAD ๋ช ๋ น์ด ์์ฒด๋ ๊ฐ๊ฐ ์์์ ์ด๋ฏ ADD์ LOAD์ ๊ฐ๊ฐ์ ๋ช ๋ น์ด ๋จ์๋ ์คํํ๋ ๋์ค์ ์ธํฐ๋ฝํธ ๋ฑ์ ์ํด ์ค๋จ๋ ์ ์๋ค.
๋ค๋ง, ADD์ LOAD ๊ฐ๊ฐ์ ๋ช ๋ น์ด ์์ฒด๋ง์ด ์์์ ์ด๋ฏ๋ก ADD ๋ช ๋ น์ด๋ฅผ ๋๋ธ ํ์ LOAD ๋ช ๋ น์ด๋ฅผ ์คํํ๊ธฐ ์ ๊ทธ ์ฌ์ด์๋ ์ธํฐ๋ฝํธ๊ฐ ๊ฑธ๋ ค ์ค๋จ๋ ์๋ ์๊ธฐ ๋๋ฌธ์ ์ ์ฒด์ ์ผ๋ก ๋ดค์ ๋๋ ๋น์์์ ์ด๋ผ๊ณ ํ ์ ์๋ค.
๐ ์ด๋ ๊ฒ ์ค๋ช ํ๋ฉด ์์์ฑ์ด ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ์ด๋ ํ ์๋ฏธ๋ฅผ ๊ฐ๊ณ ์๋ ์ง ์ง๊ด์ ์ธ ์ดํด๊ฐ ์ด๋ ค์ฐ๋ฏ๋ก ์ฝ๋๋ฅผ ํตํด ์์ธํ๊ฒ ๋ค๋ค๋ณด์!
public static void main(String[] args) {
int count = 0; // Atomic Operation (์์ ์ฐ์ฐ)
count++; // Non Atomic Operation (๋น์์ ์์ฐ)
}
์ฝ๋๋ฅผ ๋ณด๋ฉด “int count = 0” ๋ฌธ์ฅ์ “Atomic Operation (์์ ์ฐ์ฐ)”์ด๋ผ๊ณ ์ฃผ์์ ์ค๋ช ๋์ด ์๋๋ฐ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ์ธ์ด๋ ๊ณ ๊ธ ์ธ์ด๋ก ์ปดํจํฐ๊ฐ ์ดํดํ์ง ๋ชปํ๋ ์ธ์ด์ด๊ณ ์ปดํจํฐ๊ฐ ์ดํดํ๋ ์ธ์ด์ธ ๊ธฐ๊ณ์ด๋ก ์ปดํ์ผ๋ฌ๊ฐ ๋ฐ๊ฟ์ฃผ๊ธฐ ๋๋ฌธ์ ์คํํ ์ ์๋ ๊ฒ์ด๋ค.
“int count = 0”์ ๋จ์ํ ๋ฉ๋ชจ๋ฆฌ์ ๊ฐ์ ์ ์ฅํ๋ ๊ฒ์ผ๋ก ๊ธฐ๊ณ์ด๋ก ๋ณํํ์ฌ๋ ์์์ฑ์ ๋๊ณ ์๊ธฐ์ ์์์ ์ด๋ผ๊ณ ํํํ ์ ์๋ค.
๋ค๋ง “count++”์ ๊ธฐ๊ณ์ด๋ก ๋ณํํ๊ฒ ๋๋ฉด ์๋์ ๊ฐ์ด 3๊ฐ์ ์์ ์ผ๋ก ๋๋ ์ง๊ธฐ ๋๋ฌธ์ ๋น์์์ ์ด๋ผ๊ณ ํํํ ์ ์๋ค.
โ count ๋ณ์์ ๊ฐ์ ๊ฐ์ ธ์จ๋ค
โก count ๋ณ์์ ๊ฐ์ ์ฆ๊ฐ์ํจ๋ค
โข ๋ณ๊ฒฝ๋ count ๋ณ์๋ฅผ ์ ์ฅํ๋ค.
๐ ๊ทธ๋ ๋ค๋ฉด “๊ฐ์์ฑ”์์ ์ธ๊ธํ๋ ์ฌ๋ฌ ๊ฐ์ ์ค๋ ๋๊ฐ ๊ณต์ ์์์ Write ํ๊ฒ ๋๋ ๊ฒฝ์ฐ, ์์์ฑ์ ๋ณด์ฅํด์ผ ํ๋ ์ํฉ์์ ์์์ฑ์ ๋ณด์ฅํ์ง ์๋ ์ฆ, ๋น์์ ์ฐ์ฐ์ด ์ด๋ ํ ์ํฅ์ ๋ผ์น๋ ์ง ์์ ์ฝ๋๋ฅผ ํตํด ๋ณด๋๋ก ํ์!
public class Main {
public volatile static int count = 0; // ์บ์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ X --> ๊ฐ์์ฑ ํด๊ฒฐ
public static void main(String[] args) throws Exception {
Test t1 = new Test();
Test t2 = new Test();
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive()); // t1, t2 ์ค๋ ๋ ์ข
๋ฃ๋ ๋๊น์ง ๋๊ธฐ
System.out.println(count); // count ๋ณ์๊ฐ ์ถ๋ ฅ
}
}
class Test extends Thread {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
Main.count++;
}
}
}
์์ ์ฝ๋๋ฅผ ๊ฐ๋ตํ๊ฒ ์ค๋ช ํ๋ฉด int ํ์ ๋ณ์์ธ count๋ฅผ 10000๋ฒ์ฉ ์ฆ๊ฐ์ฐ์ฐํ๋ ์ค๋ ๋๋ฅผ 2๊ฐ ์์ฑํ๊ณ ์ค๋ ๋๊ฐ ์ข ๋ฃ๋๋ฉด ํด๋น count ๋ณ์๊ฐ์ ์ถ๋ ฅํ๋ค.
ํด๋น ์ฝ๋๋ฅผ ์คํํ๊ฒ ๋๋ฉด ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ฒ ๋๋ค.
15380 // ๋งค๋ฒ ์คํํ ๋๋ง๋ค, ๊ฐ์ด ๋ค๋ฅด๋ค
์์ํ๋ ๊ฒฐ๊ณผ๋ ๋ ๊ฐ์ ์ค๋ ๋์์ ๊ฐ๊ฐ 10000๋ฒ์ฉ ์ฆ๊ฐ์ฐ์ฐํ์ฌ “20000”์ด ์ถ๋ ฅ๋๊ธฐ๋ฅผ ๊ธฐ๋ํ์ง๋ง ๋งค๋ฒ ์คํํ ๋๋ง๋ค ๋ค๋ฅธ ๊ฐ์ ์ถ๋ ฅํ๋ค.
์์ ๊ฐ์ ํ์์ด ๋ฐ์ํ ๊ทผ๋ณธ์ ์ธ ์์ธ์ ๋น์์ ์ฐ์ฐ๋๋ฌธ์ด๋ค.
์์ธํ๊ฒ ์ค๋ช ํ์๋ฉด ์ผ๋จ ๊ณต์ ์์์ธ count ๋ณ์์ “volatile” ํค์๋๋ฅผ ์ฌ์ฉํด์ ๊ฐ์์ฑ ๋ฌธ์ ๋ ํด๊ฒฐ๋์๋ค. (์ฌ์ค์ ์์ ์ฝ๋์์ ํ์์์)
๊ทธ๋ฆฌ๊ณ ๋ ์ค๋ ๋๊ฐ ๋ชจ๋ ๊ณต์ ์์์ธ count ๋ณ์์ ์ฆ๊ฐ ์ฐ์ฐ์ ์งํํ๊ณ ์๋๋ฐ “count++” ์ฝ๋๋ ๊ธฐ๊ณ์ด ์ ์ฅ์์ 3๊ฐ์ ์์ ์ผ๋ก ์งํ๋๋ค๋ ๊ฑธ ์๊ธฐํ๊ณ ์๋์ ํ๋ฆ์ ๋ณด๋๋ก ํ์.
โ ์ฒซ ๋ฒ์งธ ์ค๋ ๋์์ ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ๋ก๋ถํฐ count ๋ณ์์ ๊ฐ์ ๊ฐ์ ธ์จ ๋ค์ ์ธํฐ๋ฝํธ๊ฐ ๋ฐ์ํ์ฌ ํด๋น ์ค๋ ๋๋ ์คํ ๋๊ธฐ ์ํ๋ก ๋ค์ด๊ฐ๋ค.
โก ๋ ๋ฒ์งธ ์ค๋ ๋์์ ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ๋ก๋ถํฐ count ๋ณ์์ ๊ฐ์ ๊ฐ์ ธ์จ๋ค.
โข ๋ ๋ฒ์งธ ์ค๋ ๋์์ count ๋ณ์์ ๊ฐ์ ์ฆ๊ฐ์ํจ๋ค.
โฃ ๋ ๋ฒ์งธ ์ค๋ ๋์์ ๊ฐ์ด ๋ณ๊ฒฝ๋ count ๋ณ์๋ฅผ ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ๋ค.
โค ์คํ ๋๊ธฐ ์ํ๊ฐ ๋ ์ฒซ ๋ฒ์งธ ์ค๋ ๋๊ฐ ์คํ ์ํ๋ก ๋ฐ๋๊ณ , count ๋ณ์์ ๊ฐ์ ์ฆ๊ฐ์ํจ๋ค.โฅ ๋ ๋ฒ์งธ ์ค๋ ๋์์ ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ๋ก๋ถํฐ count ๋ณ์์ ๊ฐ์ ๊ฐ์ ธ์จ๋ค.
โฆ ์ฒซ ๋ฒ์งธ ์ค๋ ๋์์ ๊ฐ์ด ๋ณ๊ฒฝ๋ count ๋ณ์๋ฅผ ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ๋ค.
.....
.....
์ด์ฒ๋ผ ๋น์์ ์ฐ์ฐ์ ์์ ์ด ์ฌ๋ฌ ๊ฐ๋ก ๋ถ๋ฆฌ๋์ด ์ด๋ฃจ์ด์ ธ ํ ๋ฒ์ ์ฒ๋ฆฌ๋์ง ์๊ธฐ ๋๋ฌธ์ ์์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋ํ๋ ๊ฒ์ด๋ค.
Synchronized ํค์๋
๋ฐ๋ผ์, ์์ ๊ฐ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Java์์๋ "Synchronized" ํค์๋๋ฅผ ์ ๊ณตํ๋ค.
“Synchronized” ํค์๋๋ ๋ฉ์๋์ ์ฌ์ฉํ ์ ์๊ณ , ํด๋น ํค์๋๊ฐ ๋ถ์ ๋ฉ์๋๋ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ ํ ์ค๋ ๋๋ง ์ฌ์ฉํ ์ ์๋๋ก Lock์ ๊ฑธ์ด๋๋ค.
์์ ์์ ์ฝ๋๋ฅผ Synchronized ํค์๋๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์๋์ ๊ฐ์ด ๋ฐ๊ฟ ์ ์๋ค.
public class Main {
public static int count = 0;
synchronized public static void add() {
count++;
}
public static void main(String[] args) throws Exception {
Testthread t1 = new Testthread();
Testthread t2 = new Testthread();
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive());
System.out.println(count);
}
}
class Testthread extends Thread {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
Main.add();
}
}
}
์ฝ๋๋ฅผ ์คํํด๋ณด๋ฉด ์ถ๋ ฅ๊ฒฐ๊ณผ๋ก “20000”์ด ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๐ ์ง๊ธ๊น์ง์ ๋ด์ฉ์ ์ ๋ฆฌํ๋ฉด ์์์ฑ์ด๋ ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ์ฌ๋ฌ ๊ฐ์ ์ค๋ ๋๊ฐ ๊ณต์ ์์์ ๋ํ ์์ (Write)์ ํ ๋, ๋ชจ๋ ๋ฐ์๋๋ ์ํ๋ฅผ ๋งํ๋ค.
์ถ๊ฐ์ ์ผ๋ก “count++”์ ๊ธฐ๊ณ์ด ์ ์ฅ์์ ๊ฐ์ ๋ถ๋ฌ์ค๊ณ , ์ฆ๊ฐ์ํค๊ณ , ์ ์ฅํ๋ 3๊ฐ์ ์์ ์ผ๋ก ๋ถ๋ฅ๋๋ ๋น์์ ์ฐ์ฐ์ด๋ผ๊ณ ํ์์ง๋ง ํ๋์ ํ๋์จ์ด๋ ๋ฐ์ดํฐ์ ์ ๊ทผ → ์ฐ์ฐ → ์ ์ฅํ๋ ๊ณผ์ ์ ํ ๋ฒ์ ์ํํ ์ ์๋ ๋ช ๋ น์ด๋ฅผ ์ง์ํ๋ค.
Java์์๋ Atomic ํด๋์ค๋ฅผ ํตํด ์ฌ์ฉํ ์ ์๋๋ฐ ์ฌ๊ธฐ์์ ์์ธํ๊ฒ ๋ค๋ฃจ์ง ์๊ณ ๊ฐ๋จํ๊ฒ ์์ ์์ ์ฝ๋์ Atomic ํด๋์ค๋ฅผ ์ฌ์ฉํ๋๊ฒ ๊น์ง๋ง ํด๋ณด๊ฒ ๋ค.
public class Main {
public static AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) throws Exception {
Testthread t1 = new Testthread();
Testthread t2 = new Testthread();
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive());
System.out.println(count.get());
}
}
class Testthread extends Thread{
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
Main.count.addAndGet(1);
}
}
}
Reference
https://yeonyeon.tistory.com/270
https://onlyfor-me-blog.tistory.com/539
https://mygumi.tistory.com/111
https://ko.wikipedia.org/wiki/%EC%9B%90%EC%9E%90%EC%84%B1
https://ko.wikipedia.org/wiki/%EC%9B%90%EC%9E%90%EC%A0%81_%ED%96%89%EC%9C%84
http://tutorials.jenkov.com/java-concurrency/volatile.html
https://ttl-blog.tistory.com/238#%F0%9F%A7%90%20volatile%EC%9D%98%20%EB%AC%B8%EC%A0%9C-1
'๐ ์ฐ์ฌ ์๋ฆฌ์ฆ > ์ฃผ๋์ด ๊ฐ๋ฐ์๊ฐ ์๋ฉด ์ข์ ๋ด์ฉ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
VSCode ์ ์ฉํ Extension ๋ชจ์ (์ ๋ฆฌ์ค) (0) | 2023.07.30 |
---|---|
Git ์์ฃผ ์ฐ์ด๋ ๋ช ๋ น์ด ๋ชจ์ (0) | 2023.07.28 |
๋ฉํฐ ์ค๋ ๋ - ๊ฐ์์ฑ (Visibility) (0) | 2023.05.03 |
๋์์ฑ (Concurrency) ๋ฐ ๋ณ๋ ฌ์ฑ (Parallelism) (0) | 2023.05.02 |
์ฝ๋ ์ปจ๋ฒค์ (Code Convention) (2) | 2023.03.08 |