일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Kotlin
- viewModelScope
- apk 빌드 과정
- 절대 주소
- http발전과정
- 디자인 패턴
- 안드로이드
- 내부 단편화
- AAC
- 자이고트
- http 역사
- 프로세스
- DiffUtil
- Dispatchers
- Android
- appcompatactivity
- 운영체제
- 플로이드워셜
- 리사이클러뷰
- 물리 메모리
- 뷰홀더
- 리사이클러뷰풀
- GetX
- NestedScrollView
- 데코레이터 패턴
- appcompatacitivity
- 상태관리
- recyclerview
- flutter
- AsyncListDiffer
- Today
- Total
hong's android
[Java] Synchronized 본문
Synchronized 사용 이유
멀티 스레드를 이용해서 한 프로그램에서 동시에 다른 스레드들을 실행할 수 있다. 하지만 동시에 동일한 변수, 객체, 메서드에 접근한다면 원하지 않은 값을 결과로 얻을 수 있다.
예를 들어,
Int limit = 10; 이란 값을 가진 클래스가 존재한다. main에서 두 개의 스레드를 실행해 메서드 실행을 완료한 후 limit의 값을 1 뺀다. (Limit 값이 0 이상에 있을 때만 값을 가져오게 하고 싶다.)
두 개의 스레드에서 동시에 limit이 위 메서드에 접근했다고 치면,
동시에 접근했을 때 두 개의 스레드 모두 조건에 만족한 뒤 메서드를 실행해서 limit 값을 1 빼준다. 그러면 결국 -1이 되므로 원하는 값을 가져오지 못한다. 위 예는 두 개의 스레드 밖에 없지만 여러 개의 스레드가 하나의 객체의 값을 사용하게 되면 제어하기 어려울 것이다.
이때 하나의 스레드만 해당 메소드를 사용할 수 있도록 다른 스레드가 접근하지 못하는 역할이 필요하다. 그런 역할을 Synchronized가 해준다. Synchronized는 메서드를 사용 중일 때 다른 메서드에서 접근하지 못하도록 lock을 걸어준다. 사용 후 unlock 한다.
하나의 프로그램은 하나의 프로세스로 실행되고 프로세스는 여러 개의 스레드로 실행된다. 하나의 프로세스에선 위와 같이 code, data heap을 공유한다. 그렇기 때문에 동시에 접근 가능하고, heap에 생성되는 객체의 값이 변경되면 다른 스레드도 공유된다. data영역에 속한 static도 마찬가지이다. 그렇기 때문에 위에 작성한 공유자원에 대한 문제가 생긴다.
반면 각 스레드들은 각각 stack을 가지고 있기 때문에 지역변수는 thread-safe 하다.
Static synchronized
일반 synchronized 메서드는 객체 단위로 동기화를 실행한다. 하지만 static synchronized은 클래스 단위로 동기화를 실행한다.
그러니까 static은 동일한 클래스 끼리는 모두 스레드가 동기화되고 일반 synchronized 해당 하나의 객체에서만 스레드가 동기화된다.
synchronized block
synchronized는 메소드에 추가하거나 블록형태로 지정해서 동기화 영역을 지정할수있다. 만약 메소드에 synchronized를 추가하는경우 메서드영역 전체를 다른 스레드가 접근을 하지 못한다. 하나의 자원만을 동기화 처리해야하는경우는 나머지 영역이 모두 처리가 안되는 채로 기다린다. 낭비가 발생한다.
Monitor 방식, synchronized block설정과 synchronized 메서드 차이점
synchronized로 스레드를 동기화하게되면 해당 클래스 객체와 모니터라는 객체가 결합된다. 모니터 객체는 락을 가지고 있는데 스레드는 해당 락을 가지고 있어야 접근할 수 있다. 락을 가지기 전 대기 상태일 때는 EntrySet에서 대기를 한다. 스레드가 조건에 맞지 않아 wait 상태일 때 waitset에서 대기한다. 그리고 notify를 호출하게 되면 해당 스레드는 entryset으로 옮겨진다.
synchronized을 메소드로 설정하는 경우 해당 메서드를 가진 객체의 모니터의 락을 가지고 있어야 해당 메서드를 실행할 수 있고 메서드의 블록으로 설정되어 있다면 블록 설정 영역의 object 모니터 락을 획득해야 한다.
선택된 스레드 : Runnable 상태, 대기 상태 스레드 : Blocked 상태
Refence.
'Develop > Java' 카테고리의 다른 글
[Java] 동시성 문제와 synchronized의 성능 (0) | 2023.02.11 |
---|---|
[Java] 제네릭, 래퍼 클래스 (0) | 2023.02.11 |
[Java] 리플렉션 (0) | 2023.01.16 |
[Java] Garbage Collector (0) | 2023.01.02 |
[Java] 자바 정리 (0) | 2022.12.31 |