반응형
쓰레드와 동기화, 그리고 교착상태에 대한 설명 ::
http://warmz.tistory.com/350
공유
아래와 같은 방식으로 run()에서 공유할 객체에 접근하는 것이 가능해진다.
예) 쓰레드가 객체를 공유하게 되는 방식 1 - Runnable 인터페이스 상속
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 |
import java.util.*;class example { public static void main(String[] args) { RunnableImpl r = new RunnableImpl(); Thread t1 = new Thread(r); Thread t2 = new Thread(r); t1.start(); t2.start(); }}class RunnableImpl implements Runnable { int iv = 0; @Override public void run() { int lv = 0; String name = Thread.currentThread().getName(); while (lv < 3) { System.out.println(name + " Local Var:" + ++lv); System.out.println(name + " Instance Var:" + ++iv); System.out.println(); } }} |
Thread-0 Local Var:1
Thread-0 Instance Var:1
Thread-0 Local Var:2
Thread-0 Instance Var:2
Thread-0 Local Var:3
Thread-0 Instance Var:3
Thread-1 Local Var:1
Thread-1 Instance Var:4
Thread-1 Local Var:2
Thread-1 Instance Var:5
Thread-1 Local Var:3
Thread-1 Instance Var:6
예) 쓰레드가 객체를 공유하게 되는 방식 2 - Thread 상속
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 |
import java.util.*;class example { public static void main(String[] args) { Data d = new Data(); MyThread t1 = new MyThread(d); MyThread t2 = new MyThread(d); t1.start(); t2.start(); }}class Data { int iv =0;}class MyThread extends Thread{ Data d; MyThread(Data d) { this.d = d; } @Override public void run() { int lv = 0; while (lv < 3) { System.out.println(getName() + " Local Var:" + ++lv); System.out.println(getName() + " Instance Var:" + ++d.iv); System.out.println(); } }} |
Thread-0 Local Var:1
Thread-0 Instance Var:1
Thread-0 Local Var:2
Thread-0 Instance Var:2
Thread-0 Local Var:3
Thread-0 Instance Var:3
Thread-1 Local Var:1
Thread-1 Instance Var:4
Thread-1 Local Var:2
Thread-1 Instance Var:5
Thread-1 Local Var:3
Thread-1 Instance Var:6
동기화(Synchronized)
- 공유 데이터에 lock을 걸어 작업중이던 쓰레드가 마칠때까지 다른 쓰레드에게 제어권이 넘어가지않게 보호한다.
- synchronized 블럭이 끝나면 lock이 풀리고 다른 쓰레드도 접근가능하게 된다.
- 교착상태(dead-lock)에 빠질 위험이 있으므로 주의한다.
synchronized를 이용한 동기화 방법
- 가능하면 메서드에 synchronized를 사용하는 메서드 단위의 동기화를 권장
|
1
2
3
4
5
6
7
8
9 |
1. 특정한 객체에 lock을 걸고자 할 때synchronized(객체의 참조변수){ // ...}2. 메서드에 lock을 걸고자할 때public synchronized void calcSum(){ // ...} |
예) 동기화 적용 전 : if문을 통과하고 출금을 수행하려는 순간 다른 쓰레드에게 제어권이 넘어가서 다른 쓰레드가 출금을 해버렸고(잔고:0) 또 이전의 쓰레드로 제어권이 넘어오면서 출금을 수행했기 때문에 잔고가 음수가 되어버렸다.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 |
import java.util.*;class example { public static void main(String[] args) { MyThread r = new MyThread(); Thread t1 = new Thread(r); Thread t2 = new Thread(r); t1.start(); t2.start(); }}class Account{ int balance = 1000; public void withDraw(int money){ if(balance >= money){ try{ Thread.sleep(1000); }catch (Exception e) {} balance -= money; } }}class MyThread implements Runnable{ Account acc = new Account(); @Override public void run() { while(acc.balance > 0){ // 100, 200, 300 중의 한 값을 임의로 선택해서 출금(withDraw) int money = (int)(Math.random() * 3 + 1) * 100; acc.withDraw(money); System.out.println("balance:" + acc.balance); } }} |
balance:500
balance:500
balance:300
balance:0
balance:-300
예) 동기화 적용 후
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 |
import java.util.*;class example { public static void main(String[] args) { MyThread r = new MyThread(); Thread t1 = new Thread(r); Thread t2 = new Thread(r); t1.start(); t2.start(); }}class Account{ int balance = 1000; // 동기화 적용 (메서드 단위의 동기화를 추천한다.) public synchronized void withDraw(int money){ /* 객체에 lock을 걸 경우 synchronized (this) { 여기에 소스 코드를 집어 넣어도 된다. } */ if(balance >= money){ try{ Thread.sleep(1000); }catch (Exception e) {} balance -= money; } }}class MyThread implements Runnable{ Account acc = new Account(); @Override public void run() { while(acc.balance > 0){ // 100, 200, 300 중의 한 값을 임의로 선택해서 출금(withDraw) int money = (int)(Math.random() * 3 + 1) * 100; acc.withDraw(money); System.out.println("balance:" + acc.balance); } }} |
결과)
balance:700
balance:700
balance:500
balance:400
balance:200
balance:0
balance:0
반응형
LIST