아래에 총 세개의 클래스를 생성하는데, 실제로 스레드를 구동시킬 main 메서드를 포함한 public 클래스 SynchronizedEx와 값이 변경되도록 하는 ShareObj 클래스, 스레드인 AddThread 클래스가 그것이다.
스레드가 thread 하나일때는 순차적으로 1, 2, 3, 4, ..., 10이 출력되는 것을 볼 수 있다. 그러나 thread2(또 다른 하나의 스레드)를 생성해 실행시켜보면, 두 스레드가 해당 자원을 점유하기 위해 경쟁하는 것을 볼 수 있다. 이 때, 하나의 스레드만 자원을 점유할 수 있도록 하는 키워드인 synchronized를 사용하면, 하나의 스레드의 작업이 모두 끝난 뒤 다른 스레드의 작업이 이루어지는 것을 볼 수 있다.
동기화란 한 번에 하나의 자원에 하나의 스레드만이 접근할 수 있게 하는 것이다. 만약 멀티 스레드 환경에서 동기화처리를 하지 않는다면, 동시 다발적으로 여러 스레드가 하나의 자원에 접근하여 공유되는 자원이 훼손될 수 있다. 예를 들어 여러 사람이 동시에 하나의 계좌를 통해 현금을 인출한다고 생각해보자. 동기화가 되지 않는다면 해당 잔고의 금액이 유효하다고 할 수 없을 것이다. 즉, 공유되는 자원을 훼손시키지 않기 위해서 멀티스레드 환경의 동기화는 매우 중요하다.
public class SynchronizedEx {
public static void main(String[] args) {
ShareObj shareObj = new ShareObj();
AddThread thread = new AddThread("HongGilDong", shareObj);
thread.start();
AddThread thread2 = new AddThread("Dooli", shareObj);
thread2.start();
}
}
class ShareObj {
int sum = 0;
public void add() {
int n = sum;
n++;
sum = n;
System.out.println(Thread.currentThread().getName() + " - " + sum);
}
public int getSum() {
return sum;
}
}
class AddThread extends Thread {
ShareObj shareObj;
public AddThread(String name, ShareObj shareObj) {
super(name);
this.shareObj = shareObj;
}
public void run() {
int i = 0;
while (i < 10) {
shareObj.add();
i++;
}
}
}
synchronized 키워드를 사용하지 않을 때(동기화하지 않은 경우)
Dooli - 2
HongGilDong - 2
Dooli - 3
HongGilDong - 4
Dooli - 5
HongGilDong - 6
Dooli - 7
Dooli - 9
Dooli - 10
HongGilDong - 8
Dooli - 11
HongGilDong - 12
Dooli - 13
HongGilDong - 14
Dooli - 15
HongGilDong - 16
Dooli - 17
HongGilDong - 18
HongGilDong - 19
HongGilDong - 20
synchronized 키워드 사용한 경우(동기화하는 경우)
HongGilDong - 1
HongGilDong - 2
HongGilDong - 3
HongGilDong - 4
HongGilDong - 5
HongGilDong - 6
HongGilDong - 7
HongGilDong - 8
HongGilDong - 9
HongGilDong - 10
Dooli - 11
Dooli - 12
Dooli - 13
Dooli - 14
Dooli - 15
Dooli - 16
Dooli - 17
Dooli - 18
Dooli - 19
Dooli - 20
그럼 짧은 시간 간격으로 스레드들을 중지시켜주면 충돌하지 않을까? sleep(int millisecond) 메서드를 사용하면 해당 시간만큼 스레드의 실행을 중지시킬 수 있다.
synchronized 키워드를 사용하지 않으면서 스레드를 10 밀리초마다 중지시켜주기
Dooli - 2
HongGilDong - 2
Dooli - 3
HongGilDong - 3
HongGilDong - 4
Dooli - 4
Dooli - 5
HongGilDong - 5
Dooli - 7
HongGilDong - 7
HongGilDong - 8
Dooli - 8
Dooli - 9
HongGilDong - 9
Dooli - 10
HongGilDong - 10
Dooli - 11
HongGilDong - 11
HongGilDong - 12
Dooli - 12
synchronized 키워드를 사용하면서 스레드를 10 밀리초마다 중지시켜주기
HongGilDong - 1
Dooli - 2
HongGilDong - 3
Dooli - 4
HongGilDong - 5
Dooli - 6
Dooli - 7
HongGilDong - 8
Dooli - 9
HongGilDong - 10
HongGilDong - 11
Dooli - 12
HongGilDong - 13
Dooli - 14
HongGilDong - 15
Dooli - 16
Dooli - 17
HongGilDong - 18
HongGilDong - 19
Dooli - 20
cf. Thread.yeild() 메서드는 현재 스레드가 다른 스레드에게 자원을 양보하게 한다. 하지만 양보한 뒤 해당 스레드의 작업이 끝날 때까지 대기하는 것이 아닌 단발성으로 양보하고, 이후에는 계속해서 자원을 점유하려 경쟁하는 것은 마찬가지이다.
'Backend > Java' 카테고리의 다른 글
문자열 등의 데이터를 다른 타입(Class)로 변환하기(ObjectMapper) (0) | 2022.05.24 |
---|---|
Java Networking) UDP 통신방식을 이용해 메세지 주고받기 (0) | 2022.04.30 |
Java Networking) 채팅 서버 만들어보기 (0) | 2022.04.25 |
Java Networking) Socket을 통한 데이터 전송 (0) | 2022.04.21 |
Java Networking) ServerSocket 생성해 Socket 연결해보기 (0) | 2022.04.18 |