자바 동시성 - 2. thread safety

roon-replica·2022년 8월 20일
0

java

목록 보기
4/6
  • 참고 자료: 자바 병렬 프로그래밍(조슈아 블로쉬 외)

개요

  • 병렬 프로그램이 단순히 스레드와 lock만 신경써서 될 일은 아니라고 함
    멀티 스레드에 안전한 코드는 변경 가능한 공유 상태에 대한 접근을 관리하는 것.
    (shared, mutable data)

  • 스레드 안전성은 데이터에 제어없이 동시에 접근하는 걸 막으려는 의미라고 함.

  • 키워드는 멀티스레드, 공유된 상태, 단일 연산 정도로 볼 수 있을듯.

thread safety

  • 여러 스레드가 객체에 접근할 때 계속 의도한대로 정확하게 동작하면 스레드 안전하다고 함

상태없는 서블릿

  • 상태없는 서블릿(다른 클래스를 참조하지도 않고, 전역변수도 없는)은 기껏해야 지역변수만 사용.
    지역변수는 스레드의 스택에 저장되고, 다른 스레드가 접근할 수 없음!!

    그래서 상태없는 객체는 항상 thread safe하다!!
@ThreadSafe
public class StatelessServlet implements Servlet{
	public void service(ServletRequest req, ServletResponse res){
    	...
    }
}

상태가 있는 서블릿

@NotThreadSafe
public class UnsafeCountingServlet implements Servlet{
	private long count;
  
	public void service(ServletRequest req, ServletResponse res){
	    ...
      count++;
      ...
  }
}

위 코드는 thread safe하지 않다는데... 흠.......
나도 비슷한 상황을 겪었는데 그 때 상황은
JPA 엔티티에 count 변수가 있었고, count 변수값을 변경하는 메서드를 따로 동기화 해주지는 않았음.
그 때랑 이 코드는 다른 상황인가..?
이 코드는 여러 스레드가 확실히 동시에 접근할 수 있음.
근데 JPA 엔티티의 count 필드 변경 함수는 1개의 http request에 의해 실행되는 것.
그래서 여러 스레드가 접근하거나 하지는 않는듯. 다른 상황이네.

race condition

  • check and act
    유효하지 않은 값을 참조해서 다음에 뭘할지 결정
    lazy initialization이 대표적인 check and act.
  • read modify write
    이전 상태를 기준으로 객체를 변경( check and act랑 비슷한 말 같은데..)
  • 경쟁 조건을 피하려면 변수가 변경되는 동안, 다른 스레드가 해당 변수를 사용하지 못하도록 막아야 함.

lock

  • 단일 연산 변수(AtomicInteger, AtomicReference<> 같은거)로는 여러 상태값의 동기화를 보장하지 못해서 lock으로 단일 연산으로 만들어줘야 함.
    여러 동작을 단일 연산으로 만드는거니까 트랜잭션의 atomic한 성질이랑 좀 비슷한 느낌이네.

  • 암묵적인 락(모니터 락)
    자바는 synchronized 구문으로 락을 제공.
    스레드가 synchronized 블록에 들어가기 전에 자동으로 확보되며, 해당 블록을 벗어날 때 해제됨.
    상호배제 방식(mutual exclusive)으로 동작한다고 함.

  • reentrant(재진입성)
    암묵적인 락은 재진입 가능하다고 함. (이미 락을 획득한 스레드가 다시 락을 확보할 수 있는거라고 함...)
    부모 클래스의 메서드를 오버라이드하고 두 메서드에 모두 synchronized가 붙어있을 때,
    재진입성이 없으면 데드락에 빠진다고 함..

lock으로 상태 보호하기

  • 락은 공유된 상태에 여러 스레드가 순차적으로 접근하도록 해서 일관된 상태를 유지할 수 있도록 해줌.

  • 하나의 락으로 동기화해야 한다?

활동성과 성능

  • 용어

    • 안전성: 잘못된 일이 생기지 않는다
    • 활동성: 원하는 일이 결국 일어난다?
    • 성능: 원하는 일이 빨리 일어나는 정도
  • synchronized 블록의 범위를 줄이면 스레드 안전성을 유지하면서 쉽게 동시성(성능)을 향상 가능.

  • 락을 얻고 해제하는 것도 부하가 꽤 된다고 함.
    그래서 synchronized 블록을 너무 잘게 쪼개는 것도 좋지 않다고 함...

Questions

  • 운영체제 책에서 나왔던 모니터락, 세마포어, 뮤텍스 등등 조금 까먹었음..
profile
집중 ➝ 프로세서↑ 시간 투자 ➝ 디스크↑

0개의 댓글