[Java] 자바 동기화(synchronezed) 하는 방법 |
환경 : Eclipse Mars, Android 4.2.2 |
자바에서 동기화란 여러 개의 스레드가 한 개의 자원을 사용하고자 할 때 해당 스레드만 제외하고 나머지는 접근을 못하도록 막는 것입니다. 자바 동기화는 synchronized 식별자로 구현하게 됩니다. 변수와 함수에 사용해서 동기화 할수 있습니다. 파워풀한 기능을 간단하게 사용할수 있다는 장점이 있지만 남발하면 안됩니다. 성능상에 문제를 줄수 있기 때문입니다.
▼ 아래 소스 처럼 synchronized 식별자는 함수와 변수에 사용이 가능합니다. 변수에 사용할때는 블록을 지정하시고 그안에 코드를 넣습니다. 이렇게 스레드를 처리해야 되는 경우는 하나의 객체에 여러 스레드가 접근해서 처리할 때 입니다.
// 1. 함수에 사용하는 경우 public synchronized void method() { //code } // 2. 객체 변수에 사용하는 경우 private Object obj = new Object(); public void exampleMethod() { synchronized(obj) { //code } }
▼ 아래 샘플은 3개의 스레드가 돌아가면서 User 클래스에 있는 Add 함수를 호출하는 과정입니다. add() 함수를 동기화하지 않고 그대로 두게 되면 출력값이 차례대로 되지 않고 바뀌는 경우가 생깁니다. 예를 들어 B2 스레드가 번호를 4로 증가하고 출력할려고 하는데 C3 스레드가 방금 증가한 4에 하나를 더해서 먼저 5를 출력한 것입니다. 그래서 아래 결과값에 B2, C3 가 뒤바뀐 것입니다.
class User { private int userNo = 0; // 임계 영역을 지정하는 synchronized메소드 public void add(String name) { System.out.println(name + " : " + userNo++ + "번째 사용"); } } class UserThread extends Thread { User user; UserThread(User user, String name) { super(name); this.user = user; } public void run() { try { for (int i = 0; i < 3; i++) { user.add(getName()); sleep(500); } } catch (InterruptedException e) { System.err.println(e.getMessage()); } } } public class SyncThread { public static void main(String[] args) { User user = new User(); // 3개의 스레드 객체 생성 UserThread p1 = new UserThread(user, "A1"); UserThread p2 = new UserThread(user, "B2"); UserThread p3 = new UserThread(user, "C3"); // 스레드 스케줄링 : 우선순위 부여 p1.setPriority(p1.MAX_PRIORITY); p2.setPriority(p2.NORM_PRIORITY); p3.setPriority(p3.MIN_PRIORITY); System.out.println("-----------------------"); System.out.println("sychronized 적용안한 경우"); System.out.println("-----------------------"); // 스레드 시작 p1.start(); p2.start(); p3.start(); } }
// 결과 ----------------------- sychronized 적용안한 경우 ----------------------- A1 : 0번째 사용 B2 : 1번째 사용 C3 : 2번째 사용 A1 : 3번째 사용 C3 : 5번째 사용 B2 : 4번째 사용 C3 : 7번째 사용 A1 : 6번째 사용 B2 : 8번째 사용
▼ 이렇게 동기화를 하지 않으면 어떤 일이 발생할지 모릅니다. 사용자가 의도한대로 차례대로 출력할려면 출력이 끝날 때 까지 add() 함수로 아무도 못들어오게 막아야 겠죠. 아래 소스는 add() 함수에 synchronized 적용한 것입니다. 번호 증가가 차례대로 되는 것을 알수 있습니다.
class User { private int userNo = 0; // 임계 영역을 지정하는 synchronized메소드 public synchronized void add(String name) { System.out.println(name + " : " + userNo++ + "번째 사용"); } } class UserThread extends Thread { User user; UserThread(User user, String name) { super(name); this.user = user; } public void run() { try { for (int i = 0; i < 3; i++) { user.add(getName()); sleep(500); } } catch (InterruptedException e) { System.err.println(e.getMessage()); } } } public class SyncThread { public static void main(String[] args) { User user = new User(); // 3개의 스레드 객체 생성 UserThread p1 = new UserThread(user, "A1"); UserThread p2 = new UserThread(user, "B2"); UserThread p3 = new UserThread(user, "C3"); // 스레드 스케줄링 : 우선순위 부여 p1.setPriority(p1.MAX_PRIORITY); p2.setPriority(p2.NORM_PRIORITY); p3.setPriority(p3.MIN_PRIORITY); System.out.println("-----------------------"); System.out.println("sychronized 적용안한 경우"); System.out.println("-----------------------"); // 스레드 시작 p1.start(); p2.start(); p3.start(); } }
// 결과 ----------------------- sychronized 적용안한 경우 ----------------------- A1 : 0번째 사용 C3 : 1번째 사용 B2 : 2번째 사용 A1 : 3번째 사용 B2 : 4번째 사용 C3 : 5번째 사용 A1 : 6번째 사용 B2 : 7번째 사용 C3 : 8번째 사용
'자바(JAVA)' 카테고리의 다른 글
[Java] 자바 라이브러리 추가하는 여러가지 방법 – Eclipse 사용 (1) | 2015.06.07 |
---|---|
[Java] 자바 맵 클래스 HashMap 을 사용하는 방법 (2) | 2015.06.01 |
[Java] 자바 디컴파일러 다운로드 사용법, JD-Eclipse 이클립스 셋팅해서 사용하기 (0) | 2015.05.27 |
자바 Java 버전 변경하기, 이클립스에서 설정 변경 하는 방법 (0) | 2015.05.25 |
[Java] 자바 네트워크 프로그램 TCP/IP ServerSocket 이용, 서버시간을 가져오는 샘플 (3) | 2015.05.14 |
[Java] 자바 날짜 계산하는 다양한 방법, GregorianCalendar, SimpleDateFormat (5) | 2015.05.13 |
[Java] 자바 구구단 출력하는 방법 (0) | 2015.05.11 |
자바 객체 직렬화 방법 ObjectInputStream, ObjectOutputStream (0) | 2015.05.10 |