2개의 Thread A, B가 동시에 공유자원 printer를 사용할 경우 Thread Interfenrence(스레드 간섭)이 발생함.
Printer.class
public class Printer {
//문자열을 한 글자당 1초씩 소요하며 출력
public void println(String str) {
for (char c : str.toCharArray()) {
System.out.print(c);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
System.out.println();
}
}
SharedPrinterEx.class
public class SharedPrinterEx {
public static void main(String[] args) {
Printer printer = new Printer();
//프린터를 사용하는 스레드들
new Thread(() -> printer.println("ABCDEF")).start();
new Thread(() -> printer.println("abcdef")).start();
}
}
출력
AaBbCcdDEefF//Thread Interfenrence 발생!
Thread Interfenrence를 막기 위해서 syncronized를 사용한다!
Printer.class
public class Printer {
//문자열을 한 글자당 1초씩 소요하며 출력
public synchronized void println(String str) {
for (char c : str.toCharArray()) {
System.out.print(c);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
System.out.println();
}
}
SharedPrinterEx.class
public class SharedPrinterEx {
public static void main(String[] args) {
Printer printer = new Printer();
//프린터를 사용하는 스레드들
new Thread(() -> printer.println("ABCDEF")).start();
new Thread(() -> printer.println("abcdef")).start();
}
}
출력
ABCDEF
abcdef
한 스레드가 공유자원 사용을 마치고 다음 스레드가 사용할 수 있도록 syncronized(동기화)된다!
RestRoom.class
public class RestRoom {
//화장실을 사용하는데 1초가 걸림.
public void use() {
System.out.printf("%s : 화장실에 들어갔다\n", Thread.currentThread());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("%s : 화장실에 나왔다.\n", Thread.currentThread());
}
}
SharedRestRoomEx.class
public class RestRoom {
//화장실을 사용하는데 1초가 걸림.
public void use() {
System.out.printf("%s : 화장실에 들어갔다\n", Thread.currentThread());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("%s : 화장실에 나왔다.\n", Thread.currentThread());
}
}
출력
Thread[Thread-0,5,main] : 화장실에 들어갔다
Thread[Thread-1,5,main] : 화장실에 들어갔다
Thread[Thread-2,5,main] : 화장실에 들어갔다
Thread[Thread-1,5,main] : 화장실에 나왔다.
Thread[Thread-2,5,main] : 화장실에 나왔다.
Thread[Thread-0,5,main] : 화장실에 나왔다.
//화장실에 동시에 2명이 들어가있는 불상사가 발생(Thread Interference)
RestRoom.class
public class RestRoom {
//화장실을 사용하는데 1초가 걸림.
public synchronized void use() {
System.out.printf("%s : 화장실에 들어갔다\n", Thread.currentThread());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("%s : 화장실에 나왔다.\n", Thread.currentThread());
}
}
SharedRestRoomEx.class
public class RestRoom {
//화장실을 사용하는데 1초가 걸림.
public void use() {
System.out.printf("%s : 화장실에 들어갔다\n", Thread.currentThread());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("%s : 화장실에 나왔다.\n", Thread.currentThread());
}
}
출력
Thread[Thread-0,5,main] : 화장실에 들어갔다
Thread[Thread-0,5,main] : 화장실에 나왔다.
Thread[Thread-1,5,main] : 화장실에 들어갔다
Thread[Thread-1,5,main] : 화장실에 나왔다.
Thread[Thread-2,5,main] : 화장실에 들어갔다
Thread[Thread-2,5,main] : 화장실에 나왔다.
//화장실에 1명만 들어가있는 상태(Thread Interference발생하지 않음.)
sychronized는 주의해서 사용해야함.화징실의 경우는 공유하며 사용할 수 없지만 TV시청같은 경우는 동시에 시청해도 무방하므로 남발하면 안된다.
ex3)synchronized block
public class RestRoom {
//화장실을 사용하는데 1초가 걸림.
public void use() {
synchronized (this) {//화장실 사용에만 동기화함.
System.out.printf("%s : 화장실에 들어갔다\n", Thread.currentThread());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("%s : 화장실에 나왔다.\n", Thread.currentThread());
}
try{//동기화되지 않은 부분
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("%s : 손을 씻었다.\n", Thread.currentThread().getName());
}
}
메서드 내부에서 꼭 동기화가 필요한 부분만 동기화해야한다.