状態管理のためのRefs、Agents、Atoms
Clojureの中核的な並行性プリミティブを使い、スレッド間で可変状態を安全に管理する方法を学びます。
「状態管理のためのRefs、Agents、Atoms」はCoddyKit上の無料Clojure Functional Programming & JVM Backend Developmentレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応の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時間対応のAIチューター)、Clojure Functional Programming & JVM Backend Developmentコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Clojure Functional Programming & JVM Backend Developmentコースには全4レッスンが含まれています。
「状態管理のためのRefs、Agents、Atoms」で何を学びますか?
Clojureの中核的な並行性プリミティブを使い、スレッド間で可変状態を安全に管理する方法を学びます。 ブラウザで直接実行するハンズオンコードでClojure Functional Programming & JVM Backend Developmentを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Clojure Functional Programming & JVM Backend Developmentを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのClojure Functional Programming & JVM Backend Developmentは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「状態管理のためのRefs、Agents、Atoms」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このClojure Functional Programming & JVM Backend Developmentレッスンでコードを書いて実行できますか?
はい。すべてのClojure Functional Programming & JVM Backend Developmentレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 状態管理のためのRefs、Agents、Atoms
- ソフトウェアトランザクショナルメモリ(STM)
- Promise、Future、非同期処理
- core.asyncのChannelとgoブロック