<?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: podboq</title>
    <description>The latest articles on DEV Community by podboq (@podboq).</description>
    <link>https://dev.to/podboq</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%2F4117392%2F3d6ece34-d911-442a-8599-082f21999490.png</url>
      <title>DEV Community: podboq</title>
      <link>https://dev.to/podboq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/podboq"/>
    <language>en</language>
    <item>
      <title>atomic and mutex never ensure the execution order of threads</title>
      <dc:creator>podboq</dc:creator>
      <pubDate>Thu, 10 Sep 2026 13:02:35 +0000</pubDate>
      <link>https://dev.to/podboq/atomic-and-mutex-never-ensure-the-execution-order-of-threads-2p1b</link>
      <guid>https://dev.to/podboq/atomic-and-mutex-never-ensure-the-execution-order-of-threads-2p1b</guid>
      <description>&lt;h2&gt;
  
  
  synopsis
&lt;/h2&gt;

&lt;p&gt;whether one thread runs first or the other,is determined by the operating system's scheduling,which naturally results in a disorderly sequence.atomic and mutex can't guarantee the order.&lt;/p&gt;

&lt;p&gt;Each core of a modern CPU has its own private L1/L2 cache and shares a L3 cache.When thread 1 modifies data,for performance reasons,it does not immediately write it back to main memory.Instead,it first writes it to the core's Store Buffer,and then asynchronously flushes it back to the cache/main memory.At this time,the core where thread 2 is located is completely unaware of this modification,and it still reads the old value from its own cache.Supplementary:The CPU has the MESI cache coherence protocol,but it can only guarantee "eventual cache coherence" and cannot guarantee "immediate visibility".The Store Buffer is a performance optimization designed to mask the delay of cache coherence.&lt;/p&gt;

&lt;p&gt;When the compiler enables optimization(such as O2),it will directly cache frequently accessed variables in registers,without reading or writing memory throughout the process.For example,if a flag bit is repeatedly read in a loop,the compiler may only read memory the first time,and always read from the register thereafter,completely ignoring any changes made to the memory value by other threads.&lt;/p&gt;

&lt;h2&gt;
  
  
  std::atomic
&lt;/h2&gt;

&lt;p&gt;It automatically prevents the compiler caching value in registers,ensuring every read and write access memory directly.&lt;/p&gt;

&lt;p&gt;Automatically insert CPU memory barriers of the corresponding level to fore a flush of the Store Buffer and invalidate the cache,ensuring that modifications are visible to other threads.&lt;/p&gt;

&lt;p&gt;At the same time,it ensures the atomic of single read-write operations,preventing the torn values during reads.&lt;/p&gt;

&lt;h2&gt;
  
  
  std::mutex
&lt;/h2&gt;

&lt;p&gt;The semantics of mutex locks inherently include a complete memory barrier:the acquire semantics are executed when locking,and the release semantics are executed when unlocking.As long as both threads correctly lock/unlock before and after accessing shared data,visibility and atomic are naturally guaranteed.&lt;/p&gt;

&lt;p&gt;Applicable scenarios:Scenarios where shared data is a complex structure and requires multiple steps of operation;the disadvantage is that the overhand is greater than that of atomic,with thread switching costs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory Fence
&lt;/h2&gt;

&lt;p&gt;This is a more fundamental mechanism,akin to manually inserting "synchronization points",which forces the CPU to flush the store buffer and invalidation read buffer,ensuring the read-write order and visibility before and after the barrier.&lt;/p&gt;

&lt;p&gt;C++ standard:&lt;br&gt;
std::atomic_thread_fence&lt;/p&gt;

&lt;p&gt;Windows:&lt;br&gt;
MemoryBarrier()&lt;/p&gt;

&lt;p&gt;GCC:&lt;br&gt;
_sync_synchronize()&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>performance</category>
      <category>programming</category>
    </item>
    <item>
      <title>PostMessage: worker thread post message to UI thread</title>
      <dc:creator>podboq</dc:creator>
      <pubDate>Thu, 10 Sep 2026 08:17:43 +0000</pubDate>
      <link>https://dev.to/podboq/postmessage-worker-thread-post-message-to-ui-thread-je</link>
      <guid>https://dev.to/podboq/postmessage-worker-thread-post-message-to-ui-thread-je</guid>
      <description>&lt;h2&gt;
  
  
  Synopsis
&lt;/h2&gt;

&lt;p&gt;PostMessage is one function of Windows API,worker thread can post message to UI thread via PostMessage&lt;/p&gt;

&lt;p&gt;BOOL PostMessage(&lt;br&gt;
HWND hWnd,      //target window hand&lt;br&gt;
UINT Msg,       //message type, case in callback WndProc&lt;br&gt;
WPARAM wParam,  //true message&lt;br&gt;
LPARAM lParam   //true message&lt;br&gt;
);&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;windows.h&amp;gt;

#define WM_RESULT (WM_USER + 1)

static HWND g_hWnd = NULL;
static HWND g_hStatic = NULL;

DWORD WINAPI WorkerThread(LPVOID)
{
    int sum = 0;
    for (int i = 1; i &amp;lt;= 100; ++i)
    {
        sum += i;
    }
    Sleep(1000);
    PostMessage(g_hWnd, WM_RESULT, (WPARAM)sum, 0);
    return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
    switch (msg)
    {
    case WM_CREATE:
    {
        g_hStatic = CreateWindowA("STATIC", "RESULT:waiting...", WS_CHILD | WS_VISIBLE, 20, 70, 260, 24, hWnd, NULL, NULL, NULL);
        CreateThread(NULL, 0, WorkerThread, NULL, 0, NULL);
    }
    break;

    case WM_COMMAND:
        if (LOWORD(wp) == 1)
        {
            CreateThread(NULL, 0, WorkerThread, NULL, 0, NULL);
        }
        break;

    case WM_RESULT:
    {
        char buf[64];
        wsprintfA(buf, "RESULT:%d", (int)wp);
        SetWindowTextA(g_hStatic, buf);
    }
    break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProcA(hWnd, msg, wp, lp);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
{
    WNDCLASSA wc = {0};
    wc.lpszClassName = "PostMsgDemo";
    wc.hInstance = hInst;
    wc.lpfnWndProc = WndProc;
    wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
    RegisterClassA(&amp;amp;wc);

    g_hWnd = CreateWindowA("PostMsgDemo", "PostMessage Demo", WS_OVERLAPPEDWINDOW &amp;amp; ~WS_THICKFRAME, 400, 300, 320, 180, NULL, NULL, hInst, NULL);
    ShowWindow(g_hWnd, nCmdShow);
    UpdateWindow(g_hWnd);

    MSG msg;
    while (GetMessage(&amp;amp;msg, NULL, 0, 0))
    {
        TranslateMessage(&amp;amp;msg);
        DispatchMessage(&amp;amp;msg);
    }
    return (int)msg.wParam;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Complie and Run
&lt;/h2&gt;

&lt;p&gt;cl /nologo PostMessage.cpp /link user32.lib kernel32.lib /subsystem:windows&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdqnsunktu2bivxgp5zof.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdqnsunktu2bivxgp5zof.png" alt=" " width="797" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmh83qfctswvvobzf05gl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmh83qfctswvvobzf05gl.png" alt=" " width="300" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzc06nl56b2avwbsladlm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzc06nl56b2avwbsladlm.png" alt=" " width="300" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Analysis
&lt;/h2&gt;

&lt;p&gt;DispatchMessage is the really point where WndProc be called&lt;/p&gt;

&lt;p&gt;while(GetMessage(&amp;amp;msg,NULL,0,0)){} This loop never finish on its own.This loop hangs here after program startup,processes message when they come,and  just hangs when free.When you click the x in the top right corner to send WM_QUIT,and GetMessage returns False,this loop exits.I feel this loop hangs around like a trigger&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
