2010. 8. 9. 21:32
Thread - 동기화 기법 JAVA이야기2010. 8. 9. 21:32
자바에는 메소드 전체 영역에 대해 동기화 시키지 않고 일부부만 동기화시킬 수 있도록 하는 기능이 있다.
public void getBusyFlag(){
while(true){
synchronized (this) {
if(busyFlag == null){
busyFlag = Thread.currentThread();
break;
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
플래그가 해제되면 값을 세팅하는 부분만 동기화 시킨다. 이런 사용법은 락을 소유하고 있는 범위가 좀 더 작다는 것을 제외하고는 동기화 메소드의 사용법과 비슷하다.
일반적으로 락의 범위 내에서 그 값을 바꾸는 인스턴스 변수는 동기화 블록을 위한 락 객체로 적합하지 않다.
동기화된 영역 내에 있느 코드는 바로 실행된다.
public synchronized void freeBusyFlag(){
if(getBusyFlagOwner() == Thread.currentThread()){
busyFlag = null;
}
}
private synchronized Thread getBusyFlagOwner() {
// TODO Auto-generated method stub
return busyFlag;
}
여기서 freeBusyFlag()를 호출하면 getBusyFlagOwner()메소드는 freeBusyFlag()의 동기화된 영역에 포함되어 있기 때문에 락을 해제할 이유가 없다.
$동기화의 범위가 너무 넓으면 데드락에 빠질 수 있다.
public void removeUseless(Folder file){
synchronized (file) {
if(file.isUseless()){
Cabinet directory = file.getCabinet();
synchronized (directory) {
directory.remove(file);
}
}
}
}
public void updateFolders(Cabinet dir){
synchronized (dir) {
for(Folder f = dir.first(); f != null; f = dir.next(f)){
synchronized (f) {
f.update();
}
}
}
}
&&removeUseless() 메소드에서 작업중인Folder객체가 updateFolders() 메소드에 의해 액세스 된다면 어떻게 될까?
updateFolders()는 Cabinet락을 가지고 있고 folder를 원한다(블록킹)
removeUseless는 Folder락을 가지고 있고 Cabinet을 원한다.(블록킹)
무조건 피해라! 발견하기도 어렵다..ㅠ_ㅠ
정적 메소드 초기화
클래스의 각 인스턴스마다 객체 락이 존재하는 것처럼 각 클래스마다 얻어질 수 있는 락이 존재한다. 이 락을 클래스락이라고 부른다. static Method가 호출되면, 프로그램은 메소드를 호출하기 전에 클래스 락을 얻는다. 클래스락을 얻고 메소드를 호출!
'JAVA이야기' 카테고리의 다른 글
Thread - 대기와 통지 (0) | 2010.08.10 |
---|---|
Java Inner Class (0) | 2010.08.10 |
Thread - API (0) | 2010.08.06 |
JAVA - polymorphism (0) | 2010.07.29 |
10진수를 2진수로 만들어서 요일과 대치하기 (0) | 2010.07.23 |