본문 바로가기

Dev. Java

자바 동기화(synchronezed) 하는 방법

[출처]  녹두장군 블로그


자바에서 동기화란 여러 개의 스레드가 한 개의 자원을 사용하고자 할 때 해당 스레드만 제외하고 나머지는 접근을 못하도록 막는 것입니다자바 동기화는synchronized 식별자로 구현하게 됩니다.변수와 함수에 사용해서 동기화 할수 있습니다파워풀한 기능을 간단하게 사용할수 있다는 장점이 있지만 남발하면 안됩니다성능상에 문제를 줄수 있기 때문입니다.

 

▼ 아래 소스 처럼 synchronized 식별자는 함수와 변수에 사용이 가능합니다변수에 사용할때는 블록을 지정하시고 그안에 코드를 넣습니다이렇게 스레드를 처리해야 되는 경우는 하나의 객체에 여러 스레드가 접근해서 처리할 때 입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
// 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 가 뒤바뀐 것입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
// 결과
-----------------------
sychronized 적용안한 경우
-----------------------
A1 : 0번째 사용
B2 : 1번째 사용
C3 : 2번째 사용
A1 : 3번째 사용
C3 : 5번째 사용
B2 : 4번째 사용
C3 : 7번째 사용
A1 : 6번째 사용
B2 : 8번째 사용

 

▼ 이렇게 동기화를 하지 않으면 어떤 일이 발생할지 모릅니다사용자가 의도한대로 차례대로 출력할려면 출력이 끝날 때 까지 add() 함수로 아무도 못들어오게 막아야 겠죠아래 소스는 add() 함수에 synchronized 적용한 것입니다번호 증가가 차례대로 되는 것을 알수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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();
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
// 결과
-----------------------
sychronized 적용안한 경우
-----------------------
A1 : 0번째 사용
C3 : 1번째 사용
B2 : 2번째 사용
A1 : 3번째 사용
B2 : 4번째 사용
C3 : 5번째 사용
A1 : 6번째 사용
B2 : 7번째 사용
C3 : 8번째 사용


'Dev. Java' 카테고리의 다른 글

초보 개발자를 위한 스택트레이스 읽는 법  (0) 2016.07.21
자바에서 구성이란?  (0) 2016.07.02
추상화, 캡슐화, 다형성  (0) 2016.06.29
소스 수정 기본 프로세스  (0) 2016.04.13
Java EE와 Java SE의 차이점  (0) 2016.02.13