자바 동시 프로 그래 밍 실전,학습 노트 1

1.스 레 드 안전성
정의:여러 스 레 드 가 특정한 클래스 에 접근 할 때 항상 정확 한 행 위 를 나 타 낼 수 있 으 면 이 종 류 를 스 레 드 안전 이 라 고 합 니 다.
상태 가 없 는 대상 은 반드시 스 레 드 가 안전 합 니 다.상태 가 없습니다.대상 은 어떠한 도 메 인 도 포함 되 지 않 고 다른 도 메 인 에 대한 인용 도 포함 되 지 않 습 니 다.또한 국부 변 수 는 실행 중인 스 레 드 에 만 접근 할 수 있 습 니 다.상태 가 없 는 Servlet:
public class StatelessFactorier implements Servlets {
	public void service(ServeletRequest req, ServletResponse resp) {
		BigInteger i = extractFromRequest(req);
		BigInteger[] factors = factor(i);
		encodeIntoResponse(resp, factors);
	}
}

경쟁 조건:부적 절 한 실행 순서 로 인해 부정 확 한 결과 가 발생 합 니 다.예 를 들 어 동기 화 되 지 않 은 i++
"선 검사 후 실행"의 경쟁 조건,if(instance==null)instance=new Object();"복합 작업'의 경쟁 조건:i++,읽 기,수정,쓰기 세 가지 작업 을 포함 합 니 다.
자물쇠 로 상 태 를 보호 하 다
여러 변 수 를 포함 하 는 모든 불변성 조건 에 대해 관련 된 모든 변 수 는 같은 자물쇠 로 성능 과 동시성 을 동시에 고려 하 는 인수 분해 Servlet 이 필요 합 니 다.
public class CachedFactorizer extends GenericServlet implements Servlet {
    @GuardedBy("this") private BigInteger lastNumber;
    @GuardedBy("this") private BigInteger[] lastFactors;
    @GuardedBy("this") private long hits;
    @GuardedBy("this") private long cacheHits;

    public synchronized long getHits() {
        return hits;
    }

    public synchronized double getCacheHitRatio() {
        return (double) cacheHits / (double) hits;
    }

    public void service(ServletRequest req, ServletResponse resp) {
        BigInteger i = extractFromRequest(req);
        BigInteger[] factors = null;
        synchronized (this) {
            ++hits;
            if (i.equals(lastNumber)) {
                ++cacheHits;
                factors = lastFactors.clone();
            }
        }
        if (factors == null) {
        //               ,        
            factors = factor(i);
            synchronized (this) {
                lastNumber = i;
                lastFactors = factors.clone();
            }
        }
        encodeIntoResponse(resp, factors);
    }
}


2.대상 의 공유
1.컴 파 일 러,프로세서 또는 실행 시 프로그램의 실행 순 서 를 정렬 합 니 다.동기 화 되 지 않 을 때 다 중 스 레 드 상황 에서 변 수 를 읽 고 쓰 는 작업 에 오류 가 발생 할 수 있 습 니 다.2.자 물 쇠 를 추가 하면 상호 배척 과 메모리 의 가시 성 을 확보 할 수 있 고 이전 스 레 드 작업 의 결 과 를 다음 스 레 드 에 볼 수 있 습 니 다.3.비 volatile 형식의 long 과 double 변 수 는 jvm 에서 64 비트 의 읽 기와 쓰기 동작 을 두 개의 32 비트 로 분해 할 수 있 습 니 다.4.volatile 변 수 는 가시 성 을 확보 할 수 있 습 니 다.변 수 는 volatile 형식 으로 설명 한 후에 컴 파일 러 는 이 변수의 조작 을 다른 메모리 작업 과 정렬 하지 않 고 레지스터 나 다른 프로세서 가 보이 지 않 는 곳 에 캐 시 하지 않 습 니 다.읽 을 때 메 인 메모리 에서 작업 메모리 로 읽 어 가시 성 을 확보 합 니 다.
대상 발표 및 일출
대상 구조 가 완성 되 기 전에 발표 하여 안전성 을 파괴 하 다.발표 하지 말 아야 할 대상 을 일출 이 라 고 합 니 다.호출 자 는 getStates()방법 을 통 해 개인 states 변 수 를 얻 을 수 있 습 니 다.예 를 들 어:
class UnsafeStates {
   private String[] states = new String[]{
       "AK", "AL" /*...*/
   };

   public String[] getStates() {
       return states;
   }
}


구조 방법 에서 this 인용 일출 이 나타 날 수 있 으 며 공장 방법 을 사용 하면 this 인용 구조 과정 에서 일출 을 방지 할 수 있다.
3.기초 동기 화(동시 다발)류
용기 의 숨겨 진 교체,예 를 들 어 toString,hashCode 와 equals 방법 을 호출 할 때 암시 적 으로 교체 되 고 모든 교체 부분 에 잠 금 처 리 를 해 야 합 니 다.CopyOnWriteArrayList,기록 할 때 복사 하고 수정 할 때마다 새 용기 사본 을 만 들 고 다시 발표 합 니 다.대기 열과 생산자-소비자 모드 를 막 고 응용:스 레 드 탱크 와 작업 대기 열의 조합.
동기 화 도구 클래스(스 레 드 간 통신 방식):차단 대기 열,신 호 량(Semaphore),울타리(Barrier),폐쇄(Latch).
1.폐쇄(Latch)는 특정한 서비스 에 필요 한 다른 서비스 가 시작 되 었 는 지 확인 하거나 특정한 작업 을 하 는 모든 참여 자가 준비 되 어 있 는 지 확인 하기 위해 사용 합 니 다.Countdown Latch 는 계수 기 를 포함 하고 있 습 니 다.처음에는 정수 입 니 다.countDown 방법 으로 계수 기 를 줄 이 는 것 은 시간 이 발생 했 음 을 표시 합 니 다.await 방법 은 계수기 값 이 0 이 되 거나 스 레 드 가 중단 되 거나 시간 이 초과 되 기 를 기다 리 는 것 을 막 습 니 다.
public class TestHarness {
    public long timeTasks(int nThreads, final Runnable task)
            throws InterruptedException {
        final CountDownLatch startGate = new CountDownLatch(1);
        final CountDownLatch endGate = new CountDownLatch(nThreads);

        for (int i = 0; i < nThreads; i++) {
            Thread t = new Thread() {
                public void run() {
                    try {
                        startGate.await();
                        try {
                            task.run();
                        } finally {
                            endGate.countDown();
                        }
                    } catch (InterruptedException ignored) {
                    }
                }
            };
            t.start();
        }

        long start = System.nanoTime();
        //startGate          
        startGate.countDown();
        endGate.await();
        long end = System.nanoTime();
        return end - start;
    }
}

2.계수 신 호 량 은 특정한 자원 에 대한 작업 수량 이나 특정한 작업 수량 을 제어 하 는 데 사 용 됩 니 다.Semaphore 는 가상 허 가 를 관리 하고 있 습 니 다.acquire 는 허 가 를 받 을 때 까지 차단 합 니 다(또는 중단 되 거나 작업 시간 초과).release 방법 은 허가 신 호 량 을 되 돌려 줍 니 다.3.울 타 리 는 폐쇄 와 유사 하여 특정한 사건 이 발생 할 때 까지 스 레 드 를 막 을 수 있 고 다시 사용 할 수 있 으 며 폐쇄 는 일회 성 대상 이다.
효율 적 인 신축 결과 캐 시,Future Task 를 사용 하여 매번 조회 할 값 이 계산 되 었 는 지,없 으 면 차단 되 었 는 지,get 방법,putIfAbsent 방법 을 사용 하여 같은 Future Task 를 중복 넣 지 않도록 합 니 다.
import java.util.concurrent.*;

public class Memoizer <A, V> implements Computable<A, V> {
    private final ConcurrentMap<A, Future<V>> cache
            = new ConcurrentHashMap<A, Future<V>>();
    private final Computable<A, V> c;

    public Memoizer(Computable<A, V> c) {
        this.c = c;
    }

    public V compute(final A arg) throws InterruptedException {
        while (true) {
            Future<V> f = cache.get(arg);
            if (f == null) {
                Callable<V> eval = new Callable<V>() {
                    public V call() throws InterruptedException {
                        return c.compute(arg);
                    }
                };
                
                FutureTask<V> ft = new FutureTask<V>(eval);
                f = cache.putIfAbsent(arg, ft);
                if (f == null) {
                    f = ft;
                    ft.run();
                }
            }
            try {
                return f.get();
            } catch (CancellationException e) {
                cache.remove(arg, f);
            } catch (ExecutionException e) {
                throw LaunderThrowable.launderThrowable(e.getCause());
            }
        }
    }
}

좋은 웹페이지 즐겨찾기