- 싱글쓰레드 프로세스의 경우에는 프로세스 내에서 단 하나의 쓰레드 만을 구현하니 프로세스의 자원을 가지고 작업하는데 별 다른 문제가 없다.
- 하지만 멀티쓰레드 프로세스의 경우에는 여러 쓰레드가 하나의 프로세스를 공유하기 때문에 자원 공유에 있어서 많은 문제가 발생할 수 있다.
가령 쓰레드 A가 있다고 가정하자 처리 도중 쓰레드 B가 제어권을 넘겨받아 처리한다면
쓰레드 A는 자신이 예상하는 결과를 갖지 못할 것이다.
https://jwdeveloper.tistory.com/123?category=823919
이러한 이유로 도입된 개념이 임계 영역(critical section) , 락(lock)이다.
- 공유 데이터를 사용하는 코드의 영역을 임계 영역으로 지정 - 이때 공유 데이터는 객체
- 객체가 가지고 있는 lock을 획득한 단 하나의 Thread 만이 임계 영역의 코드를 수행 가능
- lock을 반납하고 해당 lock을 획득한 그다음 Thread가 또다시 코드를 수행한다.
synchronized를 이용한 동기화
예제 코드
잔고가 비어있지 않을 때 인출
public class SynchronizedEx2 implements Runnable{
Account account = new Account();
@Override
public void run() {
while (account.getBalance() > 0) {
int money = (int) (Math.random() * 3 + 1) * 100;
account.withdraw(money);
System.out.println("balance : "+ account.getBalance());
}
}
}
잔고는 1000이고 인출하려는 금액이 현재 잔고보다 적거나 같을 때만 인출 가능
public class Account {
private int balance = 1000;
public int getBalance() {
return balance;
}
public void withdraw (int money) {
if (balance >= money) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
balance -= money;
}
}
}
하나의 프로세스에 두 개의 쓰레드를 돌린다.
public class SynchronizedEx {
public static void main(String[] args) {
Runnable runnable = new SynchronizedEx2();
new Thread(runnable).start();
new Thread(runnable).start();
}
}
인출하려는 금액이 현재 잔고보다 적거나 같을 때만 인출 가능하다고 했는데 잔고는 -100이다.
이유는 if 조건을 통과하기 직전에 다른 Thread가 끼어들어 인출을 하였기 때문이다. if를 통과한 직후 이기 때문에 막을 방법이 없는 것이다.
해결 방법 : synchronized 키워드를 붙여서 임계 영역을 지정하자
public synchronized void withdraw (int money) {
if (balance >= money) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
balance -= money;
}
}
코드 참조
https://github.com/mike6321/PURE_JAVA/tree/master/Thread
'Java > Java' 카테고리의 다른 글
(JAVA) Integer Cache (0) | 2020.01.29 |
---|---|
(JAVA) wait() 와 notify() (0) | 2020.01.26 |
(JAVA) 쓰레드의 실행제어 - join() (0) | 2020.01.25 |
(JAVA) 쓰레드의 실행제어 - suspend(), resume(), stop(), yield() (0) | 2020.01.25 |
(JAVA) 쓰레드의 실행제어 - interrupt(), interrupted() (0) | 2020.01.25 |