<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ThinkerQAQ</title>
    <description>The latest articles on DEV Community by ThinkerQAQ (@thinkerqaq).</description>
    <link>https://dev.to/thinkerqaq</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4126248%2Fbec4315b-4ae8-49be-9969-f39dee5d4ad9.png</url>
      <title>DEV Community: ThinkerQAQ</title>
      <link>https://dev.to/thinkerqaq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thinkerqaq"/>
    <language>en</language>
    <item>
      <title>Concurrency Programming (0): The Problem Space and Scope</title>
      <dc:creator>ThinkerQAQ</dc:creator>
      <pubDate>Tue, 15 Sep 2026 12:10:13 +0000</pubDate>
      <link>https://dev.to/thinkerqaq/concurrency-programming-0-the-problem-space-and-scope-1ig5</link>
      <guid>https://dev.to/thinkerqaq/concurrency-programming-0-the-problem-space-and-scope-1ig5</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;1. Define the Scope First&lt;/li&gt;
&lt;li&gt;2. Start with a Shared Variable&lt;/li&gt;
&lt;li&gt;
3. Two Main Coordination Models

&lt;ul&gt;
&lt;li&gt;3.1 Shared Memory: Protect Shared State with Synchronization&lt;/li&gt;
&lt;li&gt;3.2 Message Passing: Coordinate through Messages&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;4. Why Does This Code Work Correctly?&lt;/li&gt;
&lt;li&gt;5. Languages Need to Define Concurrency Semantics&lt;/li&gt;
&lt;li&gt;6. Why Do We Still Need to Go Down to the Hardware?&lt;/li&gt;
&lt;li&gt;7. Next: Start with the Hardware&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Define the Scope First
&lt;/h2&gt;

&lt;p&gt;This series discusses only:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Concurrency within a single process on a single machine.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, the focus is on multiple execution units inside the same process.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java Thread / Virtual Thread;&lt;/li&gt;
&lt;li&gt;Go Goroutine;&lt;/li&gt;
&lt;li&gt;Python Thread / asyncio Task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inter-process communication, distributed systems, and network communication are outside the scope.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Start with a Shared Variable
&lt;/h2&gt;

&lt;p&gt;Suppose a process contains this variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;count = 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now there are two execution units:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Thread A                    Thread B

count++                     count++
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If A and B each execute once, is the final result guaranteed to be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;count = 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;count++&lt;/code&gt; can be logically broken down into three steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;read count
compute count + 1
write count back
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the following interleaving is possible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;initial: count = 0

Thread A                    Thread B

read count -&amp;gt; 0
compute count + 1 -&amp;gt; 1
                            read count -&amp;gt; 0
                            compute count + 1 -&amp;gt; 1
write count -&amp;gt; 1
                            write count -&amp;gt; 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final value becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;count = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both threads complete a &lt;code&gt;+1&lt;/code&gt;, but because they read the same old value &lt;code&gt;0&lt;/code&gt;, both compute the result as &lt;code&gt;1&lt;/code&gt;, and one update is overwritten.&lt;/p&gt;

&lt;p&gt;The key problem is that two threads modify the same &lt;code&gt;count&lt;/code&gt; state concurrently:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Multiple execution units access and modify the same state at the same time.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Within one process on one machine, execution units mainly coordinate around shared data in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shared Memory / Shared State&lt;/strong&gt;: multiple execution units directly access the same state;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message Passing&lt;/strong&gt;: execution units exchange information through messages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can use the same &lt;code&gt;count++&lt;/code&gt; example to see how each model handles the problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Two Main Coordination Models
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1 Shared Memory: Protect Shared State with Synchronization
&lt;/h3&gt;

&lt;p&gt;With shared memory, multiple execution units directly access the same state. Continue with &lt;code&gt;count&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Java, the shared state can be protected with synchronization, for example &lt;code&gt;synchronized&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;synchronized&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both threads still access the same &lt;code&gt;Counter&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Thread A                    Thread B

counter.increment()         counter.increment()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But because of &lt;code&gt;synchronized&lt;/code&gt;, the two threads cannot enter the critical section in &lt;code&gt;increment()&lt;/code&gt; at the same time.&lt;/p&gt;

&lt;p&gt;Suppose Thread A acquires the lock first. The execution becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;initial: count = 0

Thread A                         Thread B

request to enter increment()
acquire lock
                                 request to enter increment()
                                 cannot acquire the same lock; wait
read count       -&amp;gt; 0
compute count+1  -&amp;gt; 1
write count      -&amp;gt; 1
leave critical section and release lock
                                 acquire lock
                                 read count       -&amp;gt; 1
                                 compute count+1  -&amp;gt; 2
                                 write count      -&amp;gt; 2
                                 leave critical section and release lock

final: count = 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Thread B acquires the lock first, the order is reversed but the result is still &lt;code&gt;2&lt;/code&gt;. What matters is not which thread runs first. What matters is that another thread cannot enter the same critical section before one complete &lt;code&gt;read → compute → write&lt;/code&gt; sequence finishes.&lt;/p&gt;

&lt;p&gt;The interleaving in which both threads read &lt;code&gt;0&lt;/code&gt; therefore no longer occurs.&lt;/p&gt;

&lt;p&gt;Go and Python provide similar mechanisms:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Go      -&amp;gt; Mutex
Python  -&amp;gt; Lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The shared idea is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The state is still shared, but access to that state is coordinated through synchronization.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  3.2 Message Passing: Coordinate through Messages
&lt;/h3&gt;

&lt;p&gt;Another approach is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Execution units exchange messages instead of having multiple execution units directly modify the same state.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Continue with &lt;code&gt;count&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, in Go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;increments&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// Counter Owner Goroutine&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;increments&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two producer goroutines do not modify &lt;code&gt;count&lt;/code&gt; directly. They send increments to the same channel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// Goroutine A&lt;/span&gt;
    &lt;span class="n"&gt;increments&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;

&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// Goroutine B&lt;/span&gt;
    &lt;span class="n"&gt;increments&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can abstract it as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Goroutine A ── +1 ──┐
                     ├──&amp;gt; Channel ──&amp;gt; Counter Owner Goroutine ──&amp;gt; count++
Goroutine B ── +1 ──┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both goroutines only send messages. The actual &lt;code&gt;count&lt;/code&gt; is modified by a dedicated &lt;code&gt;Counter Owner Goroutine&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Java and Python have similar message-passing tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java &lt;code&gt;BlockingQueue&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Python &lt;code&gt;queue.Queue&lt;/code&gt; / &lt;code&gt;asyncio.Queue&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The shared idea is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Execution units coordinate through messages instead of directly modifying the same state concurrently.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  4. Why Does This Code Work Correctly?
&lt;/h2&gt;

&lt;p&gt;So far, we have handled the original &lt;code&gt;count++&lt;/code&gt; problem in two ways.&lt;/p&gt;

&lt;p&gt;With shared memory, we used synchronization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lock / synchronized / Mutex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With message passing, we used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Queue / Channel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there is a more fundamental question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why does this code work correctly?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To answer this question, we need to discuss concurrency from three fundamental perspectives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Atomicity&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visibility&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ordering&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Return to the original &lt;code&gt;count++&lt;/code&gt; example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Atomicity — which operations are atomic?&lt;/strong&gt; &lt;code&gt;count++&lt;/code&gt; includes a read, an increment, and a write. After A acquires the lock, why must B wait until A changes &lt;code&gt;count&lt;/code&gt; from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt; and releases the lock before entering the same critical section?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visibility — when does a write become visible?&lt;/strong&gt; After A writes &lt;code&gt;count = 1&lt;/code&gt; and releases the lock, why must B read &lt;code&gt;1&lt;/code&gt; after acquiring the same lock instead of continuing to see the old value &lt;code&gt;0&lt;/code&gt;? With a channel, why can the Counter Owner receive the &lt;code&gt;+1&lt;/code&gt; sent by a producer?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ordering — which operations have an ordering relationship?&lt;/strong&gt; Why must A's &lt;code&gt;write count = 1 → release lock&lt;/code&gt; happen before B's &lt;code&gt;acquire lock → read count = 1&lt;/code&gt;? With a channel, why must a &lt;code&gt;send +1&lt;/code&gt; happen before the corresponding &lt;code&gt;receive +1 → update count&lt;/code&gt;?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These behaviors cannot depend on one particular CPU happening to execute the program in a convenient way.&lt;/p&gt;

&lt;p&gt;Programmers need a defined set of rules they can rely on.&lt;/p&gt;

&lt;p&gt;That leads to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The concurrency semantics provided by the programming language.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  5. Languages Need to Define Concurrency Semantics
&lt;/h2&gt;

&lt;p&gt;A programming language needs to define:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;When multiple execution units access state concurrently, which behaviors are allowed and which synchronization and memory-access guarantees programmers may rely on.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Java has the:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Java Memory Model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go has the:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Go Memory Model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python is not exactly the same. In this series, the discussion mainly uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Python / CPython Concurrency Semantics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These rules need to answer three questions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;What it means for the &lt;code&gt;count&lt;/code&gt; example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Atomicity — which operations are atomic?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;count++&lt;/code&gt; contains &lt;code&gt;read → increment → write&lt;/code&gt;. Without locking, A's and B's steps can interleave and produce only &lt;code&gt;1&lt;/code&gt;. With the same lock, A must completely change &lt;code&gt;count&lt;/code&gt; from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt; before B can enter the critical section and continue from &lt;code&gt;1&lt;/code&gt; to &lt;code&gt;2&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Visibility — when does a write become visible?&lt;/td&gt;
&lt;td&gt;After A writes &lt;code&gt;count = 1&lt;/code&gt; and releases the lock, B must see &lt;code&gt;1&lt;/code&gt; after acquiring the same lock instead of using the old value &lt;code&gt;0&lt;/code&gt;. With a channel, the Counter Owner must be able to receive the producer's &lt;code&gt;+1&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ordering — which operations are ordered?&lt;/td&gt;
&lt;td&gt;For the same lock, the order is &lt;code&gt;A writes count = 1 → A releases lock → B acquires lock → B reads count = 1&lt;/code&gt;. With a channel, it is &lt;code&gt;producer sends +1 → Counter Owner receives +1 → update count&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In other words, this layer answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What may the programmer rely on?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  6. Why Do We Still Need to Go Down to the Hardware?
&lt;/h2&gt;

&lt;p&gt;Languages define rules, but those rules cannot implement themselves.&lt;/p&gt;

&lt;p&gt;Java, Go, and Python ultimately rely on several layers to turn language guarantees into behavior on a real machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Concurrency Tools / Synchronization Mechanisms
    └─ Mutex / Atomic / volatile / Channel / Queue
            ↓
Language Memory Model / Concurrency Semantics
    ├─ JMM / Go Memory Model / CPython Concurrency Semantics
    └─ implemented by HotSpot JIT / Go Compiler + Runtime / CPython Runtime
            ↓
Hardware
    ├─ Computer Architecture: Von Neumann Architecture / CPU / Memory
    ├─ Hardware Memory Model: x86-TSO / ARM Memory Model
    ├─ Instruction / CPU Primitive: LOAD / STORE / Atomic RMW / Fence
    └─ Microarchitecture: Cache / Store Buffer / Cache Coherence / Out-of-Order Execution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modern CPUs use many techniques to improve performance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU caches;&lt;/li&gt;
&lt;li&gt;store buffers;&lt;/li&gt;
&lt;li&gt;out-of-order execution;&lt;/li&gt;
&lt;li&gt;atomic instructions;&lt;/li&gt;
&lt;li&gt;different memory-ordering rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Language-level concurrency semantics ultimately have to be implemented on top of these hardware capabilities. To understand why language rules and concurrency tools work, we therefore need to understand which behaviors the hardware permits and which constraints it provides.&lt;/p&gt;

&lt;p&gt;Before going deeper into the concrete concurrency semantics of Java, Go, and Python, we need to answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What guarantees does the hardware actually provide?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  7. Next: Start with the Hardware
&lt;/h2&gt;

&lt;p&gt;The next article moves down to the hardware layer.&lt;/p&gt;

&lt;p&gt;It focuses on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;why CPUs need caches;&lt;/li&gt;
&lt;li&gt;how multiple CPU cores coordinate cached data;&lt;/li&gt;
&lt;li&gt;why store buffers and out-of-order execution affect memory-access ordering;&lt;/li&gt;
&lt;li&gt;what atomic instructions provide.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once we understand those pieces, we can return to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Java Memory Model
Go Memory Model
Python / CPython Concurrency Semantics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using those rules as the foundation, we can then discuss what guarantees mutexes provide, how runtimes and CPUs implement those guarantees, and how concrete concurrency tools such as atomics and channels fit into the picture.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;This article was first published on &lt;a href="https://thinkerqaq.github.io/en/articles/concurrency-series-00/" rel="noopener noreferrer"&gt;ThinkerQAQ's personal blog&lt;/a&gt; and syndicated here by the author. The original article may be revised over time; please refer to the personal blog for the latest version.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>architecture</category>
      <category>computerscience</category>
      <category>programming</category>
      <category>softwareengineering</category>
    </item>
  </channel>
</rss>
