(Java멀티쓰레드 디자인패턴) Single Threaded Execution
* SharedResource(공유자원) 역할
-> SharedResource 역할을 하는 클래스는 복수의 쓰레드에서 액세스한다. SharedResource는 몇개의 메소드를 가지는데 대체로 2종류로 분류된다.
-> SharedResource 역할을 하는 클래스는 복수의 쓰레드에서 액세스한다. SharedResource는 몇개의 메소드를 가지는데 대체로 2종류로 분류된다.
- safeMethod : 복수의 쓰레드에서 호출해도 아무런 문제가 없는 메소드
- unsafeMethod : 복수의 쓰레드가 호출하면 안되기 때문에 가드(Guard)가 필요한 메소드
자바에서는 unsafeMethod를 synchronized 로 함으로써 가드한다.
싱글쓰레드로 동작시켜야 하는 범위를 크리티컬 섹션이라한다.
-------------------------------------------------------------------------------------------------
<적용가능성>
- 멀티쓰레드
- 복수의 쓰레드가 액세스 할 때 : 멀티쓰레드 프로그램이더라도 모든 쓰레드가 독립적으로 동작하고 있다면 SingleThreaded Execution 패턴을 사용할 필요가 없다.
- 상태가 변화할 가능성이 있을 때 : 인스턴스가 만들어진 후에 상태가 변화할 가능성이 전혀 없다면 Single Threaded Execution 을 사용할 필요가 없다. 이것이 Immutable패턴이다.
- 안전성을 확보할 필요가 없을 때
* Single Threaded Execution의 문제점은 데드락을 일으킬 수 있다는 것이다
<크리티컬 섹션의 크기와 수행능력>
- 락을 취득하는데 시간이 걸리기 때문
->synchronized메소드에 들어갈 때에는 객체의 락을 취하게 되는데 이 처리에는 시간이 걸리게 된다.
2. 쓰레드의 충돌로 대기하게 되기 때문
-> 쓰레드 A가 크리티컬 섹션에서 처리를 실행하고 있는 동안 크리티컬 섹션에 들어가려고 했던 쓰레드 B는 블록한다. 이러한 상황을 쓰레드의 충돌(Conflict)라 한다.
충돌이 일어나면 쓰레드가 대기하는 시간만큼 전체적으로 수행능력이 떨어진다.
Hashtable
uses single lock for whole data.ConcurrentHashMap
uses multiple locks on Segment level (16 by default) instead of object level i.e. wholeMap
.
* synchronized vs lock(), unlock()
-> synchronized 는 예외처리나 return상황에서도 확실하게 락을 해제해준다. 반면에 후자는 락이 해제 되지 않을 수 있다.
그러므로
try{
.....
}
finally{
unlock();
}
해주어야 한다.
* 어떤 단위로 지켜야 하는가?
1. public synchronized void pass(String name, String address){
this.counter++;
this.name = name;
this.address = address;
check();
}
2. public synchronized void setName(String name){
this.name = name;
}
public synchronized void setAddress(String Address){
this.address = address;
}
-->1번과 2번의 차이점은 2번은 name,과 address 를 만들면 쓰레드가 각각의 필드에 따로따로 대입할 수 있게 된다는 것입니다.
* 어떤 락을 사용해서 지키고 있는가?
->synchronized 한 인스턴스를 실행하는 쓰레드는 this의 락을 취해야 한다. 어떤 인스턴스의 락을 취할 수 있는 것은 딱 한 개의 쓰레드로 한정되어 있습니다.
한편 인스턴스가 다르면 락도 다릅니다.
[어떤 락을 사용해서 지키고 있는가?] 가 특히 문제가 되는 것은 synchronized 블록이다.
synchronized 블록에서는 어떤 인스턴스의 락을 취할지를 명시적으로 지정하기 때문이다.
예) synchronized(obj){
......
}
이경우는 인스턴스를 obj로 지정하고 있는 것이다.
* 최소단위의 조작
-> 한개의 쓰레드가 synchronized메소드를 실행하는 동안 다른 쓰레드는 실행할 수 없는 것
* long과 Double 은 최소단위로 취급하지 않는다.
->Java언어 사양에서는 최소단위의 조작이 처음부터 정의 되어있습니다. 예를들어, char나 int등은 기본형(primitive)의 대입이나 참조는 최소단위이다. 또 객체 등 참조형의 대입이나 참조도 최소 단위이다. 애초부터 최소단위이므로 synchronized를 붙일 필요가 없습니다.
예외적으로 long과 double의 대입이나 참조는 최소 단위가 아니다.
long 과 double 의 대입.참조가 최소단위 조작이 아니므로 long이나 double필드를 쓰레드 사이에서 공유할 경우, 그 필드에 대한 조작은 single Threaded Execution 패턴을 사용해 이루어져야 한다.
가장 간단한 방법은 synchronized 메소드 안에서 조작하는 것이다.
다른 방법은 volatile라는 키워드를 붙이면 그 필드의 조작은 최소 단위가 된다.
-> 한개의 쓰레드가 synchronized메소드를 실행하는 동안 다른 쓰레드는 실행할 수 없는 것
* long과 Double 은 최소단위로 취급하지 않는다.
->Java언어 사양에서는 최소단위의 조작이 처음부터 정의 되어있습니다. 예를들어, char나 int등은 기본형(primitive)의 대입이나 참조는 최소단위이다. 또 객체 등 참조형의 대입이나 참조도 최소 단위이다. 애초부터 최소단위이므로 synchronized를 붙일 필요가 없습니다.
예외적으로 long과 double의 대입이나 참조는 최소 단위가 아니다.
long 과 double 의 대입.참조가 최소단위 조작이 아니므로 long이나 double필드를 쓰레드 사이에서 공유할 경우, 그 필드에 대한 조작은 single Threaded Execution 패턴을 사용해 이루어져야 한다.
가장 간단한 방법은 synchronized 메소드 안에서 조작하는 것이다.
다른 방법은 volatile라는 키워드를 붙이면 그 필드의 조작은 최소 단위가 된다.
<계수 세마포어>
계수 세마포어란 [최대 N개의 쓰레드]까지 실행 할 수있도록 설정하는 것.
java.util.concurrent 패키지에서는 계수 세마포어를 나타내는 Semaphore 클래스를 제공한다.
댓글
댓글 쓰기