Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6186897
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 24, 20262026-05-24T01:58:06+00:00 2026-05-24T01:58:06+00:00

I just asked a question involving volatile: volatile array c++ However my question spawned

  • 0

I just asked a question involving volatile: volatile array c++

However my question spawned a discussion on what volatile does.

Some claim that when using the CreateThread(), you don’t have to worry about volatiles.
Microsoft on the other hand gives an example of volatile when using two threads created by CreateThread().

I created the following sample in visual c++ express 2010, and it doesn’t matter if you mark done as volatile or not

#include "targetver.h"
#include <Windows.h>
#include <stdio.h>
#include <iostream>
#include <tchar.h>

using namespace std;

bool done = false;
DWORD WINAPI thread1(LPVOID args)
{
    while(!done)
    {

    }
    cout << "Thread 1 done!\n";
    return 0;
}
DWORD WINAPI thread2(LPVOID args)
{
    Sleep(1000);
    done = 1;
    cout << "Thread 2 done!\n";
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
DWORD thread1Id;
HANDLE hThread1;
DWORD thread2Id;
HANDLE hThread2;

hThread1 = CreateThread(NULL, 0, thread1, NULL, 0, &thread1Id);
hThread2 = CreateThread(NULL, 0, thread2, NULL, 0, &thread2Id);
Sleep(4000);
CloseHandle(hThread1);
CloseHandle(hThread2);

return 0;
}

Can you ALWAYS be sure that thread 1 will stop if done is not volatile?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-24T01:58:07+00:00Added an answer on May 24, 2026 at 1:58 am

    What volatile does:

    • Prevents the compiler from optimizing out any access. Every read/write will result in a read/write instruction.
    • Prevents the compiler from reordering the access with other volatiles.

    What volatile does not:

    • Make the access atomic.
    • Prevent the compiler from reordering with non-volatile accesses.
    • Make changes from one thread visible in another thread.

    Some non-portable behaviors that shouldn’t be relied on in cross-platform C++:

    • VC++ has extended volatile to prevent any reordering with other instructions. Other compilers don’t, because it negatively affects optimization.
    • x86 makes aligned read/write of pointer-sized and smaller variables atomic, and immediately visible to other threads. Other architectures don’t.

    Most of the time, what people really want are fences (also called barriers) and atomic instructions, which are usable if you’ve got a C++11 compiler, or via compiler- and architecture-dependent functions otherwise.

    Fences ensure that, at the point of use, all the previous reads/writes will be completed. In C++11, fences are controlled at various points using the std::memory_order enumeration. In VC++ you can use _ReadBarrier(), _WriteBarrier(), and _ReadWriteBarrier() to do this. I’m not sure about other compilers.

    On some architectures like x86, a fence is merely a way to prevent the compiler from reordering instructions. On others they might actually emit an instruction to prevent the CPU itself from reordering things.

    Here’s an example of improper use:

    int res1, res2;
    volatile bool finished;
    
    void work_thread(int a, int b)
    {
        res1 = a + b;
        res2 = a - b;
        finished = true;
    }
    
    void spinning_thread()
    {
        while(!finished); // spin wait for res to be set.
    }
    

    Here, finished is allowed to be reordered to before either res is set! Well, volatile prevents reordering with other volatile, right? Let’s try making each res volatile too:

    volatile int res1, res2;
    volatile bool finished;
    
    void work_thread(int a, int b)
    {
        res1 = a + b;
        res2 = a - b;
        finished = true;
    }
    
    void spinning_thread()
    {
        while(!finished); // spin wait for res to be set.
    }
    

    This trivial example will actually work on x86, but it is going to be inefficient. For one, this forces res1 to be set before res2, even though we don’t really care about that… we just want both of them set before finished is. Forcing this ordering between res1 and res2 will only prevent valid optimizations, eating away at performance.

    For more complex problems, you’ll have to make every write volatile. This would bloat your code, be very error prone, and become slow as it prevents a lot more reordering than you really wanted.

    It’s not realistic. So we use fences and atomics. They allow full optimization, and only guarantee that the memory access will complete at the point of the fence:

    int res1, res2;
    std::atomic<bool> finished;
    
    void work_thread(int a, int b)
    {
        res1 = a + b;
        res2 = a - b;
        finished.store(true, std::memory_order_release);
    }
    
    void spinning_thread()
    {
        while(!finished.load(std::memory_order_acquire));
    }
    

    This will work for all architectures. res1 and res2 operations can be reordered as the compiler sees fit. Performing an atomic release ensures that all non-atomic ops are ordered to complete and be visible to threads which perform an atomic acquire.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I just asked a question that helps about using generics (or polymorphism) to avoid
I just asked this question, but failed to specify that I would like to
I just asked this question and the good answers mentioned using an initialization list.
I just asked this question about using a regular expression to allow numbers between
Just asked a question about linking Boost libraries in the make file. Thanks to
I just asked this question . Which lead me to a new question :)
yesterday I just asked following question. How to customize tableView Section View - iPhone
I have just asked this question an hour ago but with regards to IE8
I asked a question [ here ] recently and it's just not providing me
I asked this question yesterday, and at the time it was just what I

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.