본문 바로가기

개발/오픈소스

나의 오픈소스 개발 일기 - 1

반응형

자바 프로젝트 Loom에서 가상 쓰레드가 등장

기존의 쓰레딩 모델과 달리 이 쓰레드는 운영체제 쓰레드와 1:1 매핑되지 않음

여러 쓰레드를 띄우고 스위칭하는게 가능해짐

하지만 스위칭 시 sync 블록으로 락을 잡으면 스위칭되지 않는 문제가 발생

 

즉 이번 이슈는 명시적 락을 이용해 sync 블록을 벗겨내는게 주요 작업

ReentrantLock을 선언하고, sync 블록 앞뒤로 lock, unlock을 호출하는 간단한 이슈

하지만 진행하면서 2가지 문제가 있었다.

 

First, 특정 자원에 sync가 걸린 경우

특정 자원의 상태값을 변경할때 동시성 제어가 필요해서 아래 2가지 방법을 사용했다.

  1. synchronized (array) {…} 이런 형태인 경우 해당 자원이 ReentrantLock을 extends하게 수정
  2. 클래스 변수로 ReentrantLock을 선언하고 해당 자원에 @GuardedBy 어노테이션을 이용해 락이 있음을 알려주기

첫번째 방법은 기존 인스턴스가 extends해서 인스턴스(ReentrantLock)를 새로 생성하지 않는다.

 

Second, 특정 자원에 sync가 걸렸는데 이미 extends 키워드를 사용하고, 메소드의 입력 파라미터로 넘어온 경우

public void putAll(RequestContext ctx) {…}

위 형태의 putAll 메소드에서 ctx에 sync가 걸린 케이스였다.

이 경우는 처음에 사용한 1, 2번 모두 구현이 불가능했다.

 

어쩔 수 없이 질문을 남겼고, 메인테이너로부터 spin lock을 이용한 CAS 구현을 제안받았다.

ctx.setAttr(MAP, newMap)) == oldMap 이 조건이 성공할때까지 계속 무한루프를 돌리는 방법이었다.

하지만 setAttr은 CAS와는 달르게 실패해도 set을 해서 원하는대로 동작하지 않는다는 코멘트를 다른 메인테이너로부터 받았다.

조건이 실패하면 set 메소드가 revert된다고 생각했는데 그게 아니었다.

 

아쉽지만 이 부분은 그대로 sync 블록으로 남겨두었다.

 

후기

객체 생성 최소화는 생각 못했던 부분이었다.

정교하게 작업이 진행되어 놀랐다.

작은 이슈에서도 동시성제어 관련된 많은 코딩을 해볼 있어 즐거운 경험이었다.

관련 링크

아르메리아 https://github.com/line/armeria/issues/4510 

openJDK https://openjdk.org/projects/loom/

PR1 https://github.com/line/armeria/pull/4551

PR2 https://github.com/line/armeria/pull/4578 

 

반응형