이중 잠 금 검사 메커니즘 의 응용

이중 잠 금 검사 와 단일 예
1. 최근 에 프로젝트 에서 집합 하 는 비동기 반전 기능 을 실현 하고 이중 잠 금 검사 체 제 를 사용 하여 동기 화 문 제 를 해결 했다. 원래 코드 는 다음 과 같다.

public void obtainNewestInterface(Context context, UpdateBean config, ObtainListener obtainListener) {

if (mUpdateObject == null) {

mObtainListeners.add(obtainListener);

if (mObtainListeners.size() <= 1) {

this.execute(null, context, config);

}

} else {

obtainListener.onSucceed(mUpdateObject);

}

}

이 함 수 는 기능 의 최신 대상 을 가 져 오 는 데 사 용 됩 니 다. 만약 이 대상 이 불 러 온 것 이 완료 되 었 다 면 (행 3) 직접 리 셋 (행 15) 합 니 다.
그렇지 않 으 면 집합 에 다시 추가 합 니 다 (행 5). 대기 열 이 로 딩 작업 (행 9) 을 실행 하지 않 으 면 시작 작업 을 불 러 올 수 있 습 니 다. 로 딩 작업 의 일부 코드 는 다음 과 같 습 니 다.


@Override

public void onPostExecute(Object result, String taskid) {

if (result != null) {

mUpdateObject = (IAd) result;

for (ObtainListener listener : mObtainListeners) {

listener.onSucceed(mUpdateObject);

mObtainListeners.clear();

}

}

}

최신 기능 대상 을 불 러 오 는 것 이 완료 되면 불 러 올 집합 (줄 9) 을 옮 겨 다 니 며 각각 되 돌리 기 (줄 11) 한 다음 비우 기 (줄 13) 합 니 다.
이것 은 논리 적 인 문제 가 없 지만 다 선형 으로 obtainNewest Interface 방법 을 동시에 호출 할 때 동기 화 문제 가 발생 할 수 있 습 니 다. 동기 화 잠 금 을 넣 지 않 아 집합 대상 에 다음 과 같은 오류 가 발생 할 수 있 습 니 다.
1. 스 레 드 A 는 로 딩 이 완 료 될 때 까지 실 행 됩 니 다. 리 셋 을 옮 길 때 스 레 드 B 는 mObtainListeners. add (obtainListener) 로 실 행 됩 니 다.동기 화 오류 가 발생 할 수 있 습 니 다.
2. 스 레 드 A 는 로 딩 이 완 료 될 때 까지 실 행 됩 니 다. 스 레 드 B 는 임 무 를 제출 해 야 하 는 지 판단 할 때 까지 실 행 됩 니 다. 이때 size = 2, 스 레 드 A 가 실 행 됩 니 다. 스 레 드 B 는 임 무 를 제출 하지 않 습 니 다. 그러면 B 임 무 는 다시 조정 되 지 않 습 니 다.
그래서 자물쇠 안전 을 추 가 했 습 니 다. 코드 는 다음 과 같 습 니 다.


public void obtainNewestInterface(Context context, UpdateBean config,

ObtainListener obtainListener) {

if (mUpdateObject == null) {

synchronized (mObtainListeners) {

mObtainListeners.add(obtainListener);

if (mObtainListeners.size() <= 1) {

this.execute(null, context, config);

}

}

} else {

obtainListener.onSucceed(mUpdateObject);

}

}

@Override

public void onPostExecute(Object result, String taskid) {

if (result != null) {

mUpdateObject = (IAd) result;

synchronized (mObtainListeners) {

for (ObtainListener listener : mObtainListeners) {

listener.onSucceed(mUpdateObject);

}

mObtainListeners.clear();

}

}

}

이렇게 하면 위 와 같은 문 제 를 해결 할 수 있 지만 자세히 음미 하면 새로운 문제 가 또 생 긴 다.
1. 스 레 드 A 는 옮 겨 다 니 며, 스 레 드 B 는 if (mUpdateObject = = null) {로 잠 겨 있 습 니 다.
2. 스 레 드 B 는 옮 겨 다 니 기 를 마치 고 집합 을 비 웁 니 다. 이때 object 는 비어 있 지 않 습 니 다. 잠 금 이 해제 되 고 스 레 드 B 는 잠 금 코드 에 들 어가 면 add 를 계속 합 니 다. 이때 size = 1 은 작업 을 계속 제출 합 니 다.
본질은 object 가 비어 있다 는 것 을 판단 하기 위해 한 번 만 불 러 오고 모든 것 을 되 돌리 기 위해 서 입 니 다. 그래서 자물쇠 안에 빈 칸 을 표시 합 니 다. 코드 는 다음 과 같 습 니 다.

public void obtainNewestInterface(Context context, UpdateBean config,

ObtainListener obtainListener) {

if (mUpdateObject == null) {

synchronized (mObtainListeners) {

//

if (mUpdateObject != null) {

obtainListener.onSucceed(mUpdateObject);

} else {

mObtainListeners.add(obtainListener);

if (mObtainListeners.size() <= 1) {

this.execute(null, context, config);

}

}

}

} else {

obtainListener.onSucceed(mUpdateObject);

}

}

//

@Override

public void onPostExecute(Object result, String taskid) {

if (result != null) {

mUpdateObject = (IAd) result;

synchronized (mObtainListeners) {

for (ObtainListener listener : mObtainListeners) {

listener.onSucceed(mUpdateObject);

}

mObtainListeners.clear();

}

}

}


해결!

좋은 웹페이지 즐겨찾기