728x90
반응형
[4] 동기화 메서드와 동기화 블럭
1. 공유 객체를 사용할 때 주의점
- 멀티 스레드가 하나의 객체를 서로 공유해서 생기는 오류
public class Calculator {
private int memory; // 공유되는 필드
public int getMemory() {
return memory;
}
// 동기화 메서드
// 하나의 스레드만 실행할 수 있도록 만들어주는 것 => 동기화 메서드 및 동기화 블럭 (synchronized)
// 이걸 사용하게 되면 지연 시간이 생긴다.
public synchronized void setMemory(int memory) {
this.memory = memory;
try {
Thread.sleep(2000); // 2초후 의미
} catch(InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + ": " + this.memory);
}
}
public class User1 extends Thread {
private Calculator calculator;
public void setCalculator(Calculator calculator) {
this.setName("User1");
this.calculator = calculator;
}
public void run() {
calculator.setMemory(100);
}
}
public class User2 extends Thread {
private Calculator calculator;
public void setCalculator(Calculator calculator) {
this.setName("User2");
this.calculator = calculator;
}
public void run() {
calculator.setMemory(50);
}
}
public class MainThreadExample {
public static void main(String[] args) {
Calculator calculator = new Calculator();
User1 user1 = new User1(); // 작업 스레드 생성
user1.setCalculator(calculator);
user1.start();
// user1 클래스에 있는 run() 메서드 실행됨
// 100이 출력 되어야 하는데 50이 출력됨
// Why? user2와 같은 calculator 객체를 사용하고 있기 때문에
// user1이 먼저 사용하고 다음에 user2가 사용하게 되는데
// 이때 같은 객체를 사용하고 있기때문에 user2가 값을 지정할때
// user1도 그 바뀐 값으로 변한다.
// 따라서 결과적으론 calculator 객체에는 50이라는 값으로 바뀌게 되었으니
// user1도 50이라는 값으로 출력된다..
User2 user2 = new User2();
user2.setCalculator(calculator);
user2.start();
// user2 클래스에 있는 run() 메서드 실행됨
}
}
[ 멀티 스레드가 하나의 객체를 공유해서 오류 발생하는 위의 예제 코드 ]
2. 동기화 메서드 및 동기화 블럭 (synchronized)
- 임계 영역(critical section): 단 하나의 스레드만 실행할 수 있는 코드 영역
- 다른 스레드는 동기화 메서드나 동기화 블럭의 실행이 끝날 때까지 대기해야 한다.
(다만, 다른 스레드는 대기하는 동안 동기화 메서드나 동기화 블럭을 호출할 수 없지만 일반 메서드는 호출할 수 있다.)
public class Calculator {
private int memory;
public int getMemory() {
return memory;
}
public synchronized void setMemory(int memory) {
this.memory = memory;
try {
Thread.sleep(2000);
} catch(InterruptedException e) {}
System.out.println(Thread.currentThread().getName() + ": " + this.memory);
}
}
public class User1 extends Thread {
private Calculator calculator;
public void setCalculator(Calculator calculator) {
this.setName("User1");
this.calculator = calculator;
}
public void run() {
calculator.setMemory(100);
}
}
public class User2 extends Thread {
private Calculator calculator;
public void setCalculator(Calculator calculator) {
this.setName("User2");
this.calculator = calculator;
}
public void run() {
calculator.setMemory(50);
}
}
// Thread 클래스를 상속받아 Thread를 정의함.
public class Family extends Thread {
Toilet toilet;
String who;
boolean key; // 초기값: false
// 생성자
public Family(String name, Toilet t) {
who = name;
toilet = t;
}
public void run() {
toilet.openDoor(who, key);
}
}
// key를 이용해서 Thread간에 충돌이 일어나지 않도록 실행순서를 맞추는 것을
// Thread의 동기화(Synchronization)라고 한다.
public class Toilet { // 화장실을 사용하는 과정을 보여주는 클래스
// 메소드의 동기화 방법
// synchronized로 선언된 openDoor() 메소드는 한번 실행이 끝나야 다음 실행이 가능함.
// 다른 Thread들은 한개의 Thread가 이 메소드의 실행을 끝낼때 까지 대기함.
public synchronized void openDoor(String name, boolean b) {
// public void openDoor( String name, boolean b ) {
if (b == false) {
System.out.println(name);
usingTime();
System.out.println("아~~~~! 시원해");
} else {
System.out.println("사용중");
}
}// openDoor() end
public void usingTime() { // 화장실 사용하는 시간
for (int i = 0; i < 100000000; i++) {
if (i == 10000) {
System.out.println("끄으응");
}
}
}// usingTime() end
}
// 5개의 Thread를 만들어 실행 시키는 클래스
public class ManageToilet {
public static void main( String[] args ) {
Toilet t = new Toilet();
// thread 생성
Family father = new Family("아버지", t );
Family mother = new Family("어머니", t );
Family sister = new Family("누나", t );
Family brother = new Family("형", t );
Family me = new Family("나", t );
/* 우선 순위 적용안됨
father.setPriority(10);
mother.setPriority(7);
sister.setPriority(5);
brother.setPriority(3);
me.setPriority(1);
*/
// 각 Thread는 Runnable 상태에 들어감
father.start();
mother.start();
sister.start();
brother.start();
me.start();
}
}
[ 동기화 메서드와 동기화 블럭 관련한 위의 예제 코드 ]
728x90
반응형
'Studying' 카테고리의 다른 글
Thread (4) | 2024.01.30 |
---|---|
리다이렉트 (Redirect) (0) | 2024.01.02 |
Rest vs Restful (2) | 2024.01.02 |
HTTP 상태 코드 (2) | 2023.10.30 |
클라우드 서비스 개념 공부 (2) | 2023.07.17 |