[clojure] Clojure 에이전트와 STM(소프트웨어 트랜잭션 메모리)

Clojure는 다중 스레드 프로그래밍을 쉽게 지원하기 위해 에이전트와 STM(소프트웨어 트랜잭션 메모리)이라는 독특한 기능을 제공합니다. 에이전트를 사용하여 병렬 처리를 쉽게 할 수 있고, STM을 사용하여 트랜잭션을 안전하게 관리할 수 있습니다. 이번 포스트에서는 Clojure의 에이전트와 STM에 대해 알아보겠습니다.

에이전트(Agent)

에이전트는 공유 상태를 안전하게 변경하기 위한 메커니즘으로, 일관된 상태의 변경을 보장합니다. 에이전트는 멀티스레드 환경에서 안전하게 상태를 변경할 수 있는데, 이는 곧 공유된 가변 상태를 다루는 훌륭한 방법입니다.

에이전트는 clojure.core/agent 를 사용하여 생성되며, send, send-off, await, alter 등의 함수를 이용하여 상태를 변경하거나 조회할 수 있습니다.

에이전트는 동시에 여러 작업을 수행할 때 특히 유용합니다. 에이전트는 비동기적으로 동작하며, 작업 완료 후 자동으로 최신 상태로 업데이트됩니다.

(def counter (agent 0))

(send counter inc) ; 상태를 변경하기 위해 send 함수를 사용

(println @counter) ; 상태를 조회하기 위해 @ 키워드를 사용

에이전트는 불변 데이터 구조를 이용한 함수적인 방식과 함께 사용하여, 병렬 프로그래밍을 보다 안전하고 간단하게 만들어 줍니다.

STM (소프트웨어 트랜잭션 메모리)

Clojure의 STM은 트랜잭션을 이용하여 병렬 프로그래밍을 보다 안전하게 합니다. STM을 사용하면 데이터 변경을 안전하게 처리할 수 있으며, 동시에 여러 스레드 간의 데이터 충돌을 방지할 수 있습니다.

STM은 일련의 작업을 원자적으로 그룹화하여 수행함으로써, 일부 작업만 성공하는 상황을 방지합니다. 만약 로직의 일부분에서 예외가 발생한다면, 해당 트랜잭션은 원자성을 유지하며 롤백됩니다.

(defn transfer [from-account to-account amount]
  (dosync
    (if (>= @from-account amount)
      (do 
        (alter from-account - amount)
        (alter to-account + amount))
      (throw (RuntimeException. "Insufficient balance")))))

STM은 clojure.core/dosync 블록을 통해 사용됩니다. 이 블록 안에서 커밋을 위한 여러 작업을 정의할 수 있으며, 이러한 작업들은 원자적으로 처리됩니다.

Clojure의 에이전트와 STM은 병렬 프로그래밍을 간편하게 만들어 주는 강력한 기능입니다. 이러한 기능들을 적절히 활용하면 프로그램의 안전성과 성능을 향상시킬 수 있습니다.

참고 자료

이상으로 Clojure 에이전트와 STM에 대해 알아보았습니다. 좀 더 심도있는 내용에 대해서는 공식 문서를 참고해 주세요.