상태 관리를 위한 Refs, Agents, Atoms
스레드 간 변경 가능한 상태를 안전하게 관리하기 위해 Clojure의 핵심 동시성 기본 요소를 사용하는 방법을 학습합니다.
상태 관리를 위한 Refs, Agents, Atoms은(는) CoddyKit의 무료 Clojure Functional Programming & JVM Backend Development 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Clojure Functional Programming & JVM Backend Development 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Clojure Functional Programming & JVM Backend Development 강의에는 총 4개의 강의가 포함되어 있습니다.
이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.
Concurrency & State Intro
Managing state in concurrent programs is tricky! When multiple parts of your code try to change the same data at once, you can run into big problems like data corruption or deadlocks.
Clojure offers powerful tools to handle shared mutable state safely and efficiently.
Clojure's State Philosophy
Clojure embraces immutability by default. This means data structures don't change after creation. But what about when you genuinely need to change something, like a counter or a user's balance?
- Clojure provides special concurrency primitives.
- These primitives manage mutable state in a controlled way.
- They ensure changes are safe, even across multiple threads.
Atoms: Independent State
An Atom is the simplest way to manage a single, independent piece of mutable state. It's great for things like counters or flags.
- Updates are synchronous and atomic (all-or-nothing).
- Atoms use a Compare-And-Swap (CAS) loop internally.
- Best for state that doesn't need to be coordinated with other pieces of state.
Atom Code Example
Let's see an Atom in action. We'll create a simple counter and update it.
(ns coddykit.core
(:gen-class))
(defn -main
"Demonstrates Clojure Atoms."
[& args]
(let [my-counter (atom 0)]
(println "Initial value:" @my-counter)
(swap! my-counter inc)
(println "After inc:" @my-counter)
(swap! my-counter + 5)
(println "After add 5:" @my-counter)))Atom `swap!` Explained
The swap! function is key for updating Atoms:
- It takes the atom, a function, and optional arguments for that function.
(swap! my-atom inc)atomically increments the value.(swap! my-atom + 5)atomically adds 5 to the value.- The function is applied to the atom's current value, and the result becomes the new value. This happens in a thread-safe way.
Refs: Coordinated State
Refs are for managing coordinated mutable state. This means you have multiple pieces of state that must change together, or not at all.
- Refs use Clojure's Software Transactional Memory (STM).
- Changes occur within a transaction (
dosyncblock). - All changes in a transaction either succeed or fail as a group.
Ref Code Example
Here's how to use Refs to transfer a value between two accounts atomically. If one fails, both revert.
(ns coddykit.core
(:gen-class))
(defn -main
"Demonstrates Clojure Refs and STM."
[& args]
(let [account-a (ref 100)
account-b (ref 50)
amount-to-transfer 20]
(println "Initial: A=" @account-a "B=" @account-b)
(dosync
(alter account-a - amount-to-transfer)
(alter account-b + amount-to-transfer))
(println "After transfer: A=" @account-a "B=" @account-b)))STM with Refs Explained
The dosync block defines a transaction:
refcreates a new Ref.alterchanges a Ref's value within a transaction. It takes the Ref, a function, and its arguments.- If any part of the
dosyncblock fails, all changes are rolled back. - This ensures atomicity: all or nothing.
Agents: Asynchronous State
Agents are designed for managing mutable state asynchronously and in isolation. They're perfect for tasks that might take time or run in the background without blocking your main thread.
- Updates are sent as messages to the Agent.
- The Agent processes these messages in a separate thread.
- This provides isolation: the agent's state changes only through its own processing.
Agent Code Example
Let's use an Agent to process a list of numbers asynchronously, summing them up.
(ns coddykit.core
(:gen-class))
(defn -main
"Demonstrates Clojure Agents."
[& args]
(let [sum-agent (agent 0)]
(println "Initial sum:" @sum-agent)
(send sum-agent + 10)
(send sum-agent + 20)
(send sum-agent + 5)
(println "Waiting for agent to finish...")
(await sum-agent) ; Wait for all sent actions to complete
(println "Final sum:" @sum-agent)))Agent Workflow
Here's how Agents work:
agentcreates a new Agent with an initial value.senddispatches a function and arguments to the agent. The function will be applied to the agent's current state on another thread.- The agent processes messages one by one in its own thread, ensuring isolated updates.
await(orawait-for) is used to block the current thread until the agent has processed all pending actions.
Choosing the Right Primitive
You've learned about Atoms, Refs, and Agents. Each has a specific purpose for managing mutable state safely.
Which of the following statements correctly describe when to use which concurrency primitive?
Recap: State Management
In this lesson, we explored Clojure's core concurrency primitives for managing mutable state safely:
- Atoms: For simple, independent, synchronous state changes.
- Refs: For coordinated, transactional state changes across multiple values using STM.
- Agents: For asynchronous, isolated state updates, processed in a separate thread.
Understanding these tools is crucial for building robust and concurrent Clojure applications!
자주 묻는 질문
“상태 관리를 위한 Refs, Agents, Atoms” 강의는 무료인가요?
네 — “상태 관리를 위한 Refs, Agents, Atoms” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Clojure Functional Programming & JVM Backend Development 강의 전체를 잠금 해제할 수 있습니다. Clojure Functional Programming & JVM Backend Development 강의에는 총 4개의 강의가 포함되어 있습니다.
“상태 관리를 위한 Refs, Agents, Atoms”에서 뭘 배우나요?
스레드 간 변경 가능한 상태를 안전하게 관리하기 위해 Clojure의 핵심 동시성 기본 요소를 사용하는 방법을 학습합니다. 브라우저에서 직접 실행하는 실습 코드로 Clojure Functional Programming & JVM Backend Development을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Clojure Functional Programming & JVM Backend Development을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Clojure Functional Programming & JVM Backend Development은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“상태 관리를 위한 Refs, Agents, Atoms” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Clojure Functional Programming & JVM Backend Development 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Clojure Functional Programming & JVM Backend Development 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 상태 관리를 위한 Refs, Agents, Atoms
- 소프트웨어 트랜잭션 메모리(STM)
- 약속, 퓨처 및 비동기 작업
- core.async 채널과 Go 블록