Simplest Mutex ever. Does this example work? Is it thread-safe?












5















I would like to ask about the simplest Mutex approach ever for multi-threading. Is the following code thread-safe (quick-n-dirty)?



class myclass
{
bool locked;
vector<double> vals;

myclass();
void add(double val);
};

void myclass::add(double val)
{
if(!locked)
{
this->locked = 1;
this->vals.push_back(val);
this->locked = 0;
}
else
{
this->add(val);
}
}

int main()
{
myclass cls;
//start parallelism
cls.add(static_cast<double>(rand()));
}


Does this work? Is it thread-safe? I'm just trying to understand how the simplest mutex can be written.



If you have any advice about my example, would be nice.



Thank you.



Thanks for saying that it doesn't work. Can you please suggest a fix which is compiler independent?










share|improve this question




















  • 5





    Making a correct mutex mechanism is a complex business. I would use something already out there.

    – andre
    Feb 11 '13 at 18:57











  • Generally, synchronization primitives such as mutexes require some atomicity (often at the CPU instruction level). Here's an interesting link I found: lists.canonical.org/pipermail/kragen-tol/1999-August/…

    – Tom
    Feb 11 '13 at 19:06











  • The simplest mutex (or synchronization construct in general) is the one you don't need ;-)

    – user395760
    Feb 11 '13 at 19:16
















5















I would like to ask about the simplest Mutex approach ever for multi-threading. Is the following code thread-safe (quick-n-dirty)?



class myclass
{
bool locked;
vector<double> vals;

myclass();
void add(double val);
};

void myclass::add(double val)
{
if(!locked)
{
this->locked = 1;
this->vals.push_back(val);
this->locked = 0;
}
else
{
this->add(val);
}
}

int main()
{
myclass cls;
//start parallelism
cls.add(static_cast<double>(rand()));
}


Does this work? Is it thread-safe? I'm just trying to understand how the simplest mutex can be written.



If you have any advice about my example, would be nice.



Thank you.



Thanks for saying that it doesn't work. Can you please suggest a fix which is compiler independent?










share|improve this question




















  • 5





    Making a correct mutex mechanism is a complex business. I would use something already out there.

    – andre
    Feb 11 '13 at 18:57











  • Generally, synchronization primitives such as mutexes require some atomicity (often at the CPU instruction level). Here's an interesting link I found: lists.canonical.org/pipermail/kragen-tol/1999-August/…

    – Tom
    Feb 11 '13 at 19:06











  • The simplest mutex (or synchronization construct in general) is the one you don't need ;-)

    – user395760
    Feb 11 '13 at 19:16














5












5








5


1






I would like to ask about the simplest Mutex approach ever for multi-threading. Is the following code thread-safe (quick-n-dirty)?



class myclass
{
bool locked;
vector<double> vals;

myclass();
void add(double val);
};

void myclass::add(double val)
{
if(!locked)
{
this->locked = 1;
this->vals.push_back(val);
this->locked = 0;
}
else
{
this->add(val);
}
}

int main()
{
myclass cls;
//start parallelism
cls.add(static_cast<double>(rand()));
}


Does this work? Is it thread-safe? I'm just trying to understand how the simplest mutex can be written.



If you have any advice about my example, would be nice.



Thank you.



Thanks for saying that it doesn't work. Can you please suggest a fix which is compiler independent?










share|improve this question
















I would like to ask about the simplest Mutex approach ever for multi-threading. Is the following code thread-safe (quick-n-dirty)?



class myclass
{
bool locked;
vector<double> vals;

myclass();
void add(double val);
};

void myclass::add(double val)
{
if(!locked)
{
this->locked = 1;
this->vals.push_back(val);
this->locked = 0;
}
else
{
this->add(val);
}
}

int main()
{
myclass cls;
//start parallelism
cls.add(static_cast<double>(rand()));
}


Does this work? Is it thread-safe? I'm just trying to understand how the simplest mutex can be written.



If you have any advice about my example, would be nice.



Thank you.



Thanks for saying that it doesn't work. Can you please suggest a fix which is compiler independent?







c++ multithreading parallel-processing global-variables mutex






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 11 '13 at 19:02







The Quantum Physicist

















asked Feb 11 '13 at 18:55









The Quantum PhysicistThe Quantum Physicist

12.1k748103




12.1k748103








  • 5





    Making a correct mutex mechanism is a complex business. I would use something already out there.

    – andre
    Feb 11 '13 at 18:57











  • Generally, synchronization primitives such as mutexes require some atomicity (often at the CPU instruction level). Here's an interesting link I found: lists.canonical.org/pipermail/kragen-tol/1999-August/…

    – Tom
    Feb 11 '13 at 19:06











  • The simplest mutex (or synchronization construct in general) is the one you don't need ;-)

    – user395760
    Feb 11 '13 at 19:16














  • 5





    Making a correct mutex mechanism is a complex business. I would use something already out there.

    – andre
    Feb 11 '13 at 18:57











  • Generally, synchronization primitives such as mutexes require some atomicity (often at the CPU instruction level). Here's an interesting link I found: lists.canonical.org/pipermail/kragen-tol/1999-August/…

    – Tom
    Feb 11 '13 at 19:06











  • The simplest mutex (or synchronization construct in general) is the one you don't need ;-)

    – user395760
    Feb 11 '13 at 19:16








5




5





Making a correct mutex mechanism is a complex business. I would use something already out there.

– andre
Feb 11 '13 at 18:57





Making a correct mutex mechanism is a complex business. I would use something already out there.

– andre
Feb 11 '13 at 18:57













Generally, synchronization primitives such as mutexes require some atomicity (often at the CPU instruction level). Here's an interesting link I found: lists.canonical.org/pipermail/kragen-tol/1999-August/…

– Tom
Feb 11 '13 at 19:06





Generally, synchronization primitives such as mutexes require some atomicity (often at the CPU instruction level). Here's an interesting link I found: lists.canonical.org/pipermail/kragen-tol/1999-August/…

– Tom
Feb 11 '13 at 19:06













The simplest mutex (or synchronization construct in general) is the one you don't need ;-)

– user395760
Feb 11 '13 at 19:16





The simplest mutex (or synchronization construct in general) is the one you don't need ;-)

– user395760
Feb 11 '13 at 19:16












7 Answers
7






active

oldest

votes


















8















Is it thread-safe?




Certainly not. If a thread is preempted between checking and setting the lock, then a second thread could acquire that lock; if control then returns to the first thread, then both will acquire it. (And of course, on a modern processor, two or more cores could be executing the same instructions simultaneously for even more hilarity.)



At the very least, you need an atomic test-and-set operation to implement a lock like this. The C++11 library provides such a thing:



std::atomic_flag locked;

if (!locked.test_and_set()) {
vals.push_back(val);
locked.clear();
} else {
// I don't know exactly what to do here;
// but recursively calling add() is a very bad idea.
}


or better yet:



std::mutex mutex;

std::lock_guard<std::mutex> lock(mutex);
vals.push_back(val);


If you have an older implementation, then you'll have to rely on whatever extensions/libraries are available to you, as there was nothing helpful in the language or standard library back then.






share|improve this answer


























  • hmmmmm. Thanks for the answers. I'm using VS2010 and g++, where the first one doesn't support mutex. Any other compiler independent idea?

    – The Quantum Physicist
    Feb 11 '13 at 19:42






  • 1





    @SamerAfach: The Boost.Thread and just::thread libraries have portable and (more or less) direct replacements for the C++11 mutex. Failing that there's the Windows API (critical sections, or whatever they call it); obviously that's not compiler-independent, so you'll need some carefully placed #defines to select which to use.

    – Mike Seymour
    Feb 11 '13 at 19:48













  • @MikeSymour if I use the boost Mutex for example (or any other Mutex), will that make the code thread-safe for other parallelization libraries, like OpenMPI and OpemMP? or does Mutex work exclusively for the parallelism of the library from which the Mutex is taken?

    – The Quantum Physicist
    Feb 12 '13 at 7:46






  • 1





    @SamerAfach: I don't quite understand the question, but I guess the answer is yes. Using a mutex correctly will serialise all sections of code that run with that mutex locked, making that code thread-safe, regardless of whatever parallelisation libraries you're using.

    – Mike Seymour
    Feb 14 '13 at 10:58











  • "regardless of whatever parallelisation libraries you're using". That answers my question. Thanks :)

    – The Quantum Physicist
    Feb 14 '13 at 11:03



















5














No, this is not thread safe. There's a race between



if(!locked)


and



this->locked = 1;


If there is a context switch between these two statements, your lock mechanism falls apart. You need an atomic test and set instruction, or simply use an existing mutex.






share|improve this answer































    5














    This code doesn't provide an atomic modification of vals vector. Consider the following scenario:



    //<<< Suppose it's 0
    if(!locked)
    { //<<< Thread 0 passes the check
    //<<< Context Switch - and Thread 1 is also there because locked is 0
    this->locked = 1;
    //<<< Now it's possible for one thread to be scheduled when another one is in
    //<<< the middle of modification of the vector
    this->vals.push_back(val);
    this->locked = 0;
    }





    share|improve this answer































      2















      Does this work? Is it thread-safe?




      No. It will fail at times.



      Your mutex will only work if other threads never do anything between the execution of these two lines:



      if(!locked)
      {
      this->locked = 1;


      ...and you have not ensured that.



      To learn about the how of mutex writing, see this SO post.






      share|improve this answer

































        2














        No, that is not thread safe.



        Consider two threads running myclass::add at more-or-less the same time. Also, imagine that the value of .locked is false.



        The first thread executes up to and including this line:



        if(!locked)
        {


        Now imagine that the system switches context to the second thread. It also executes up to the same line.



        Now we have two different threads, both believing that they have exclusive access, and both inside the !locked condition of the if.



        They will both call vals.push_back() at more-or-less the same time.



        Boom.






        share|improve this answer































          1














          Others have already shown how your mutex can fail, so I won't rehash their points. I will only add one thing: The simplest mutex implementation is a lot more complicated than your code.



          If you're interested in the nitty gritty (or even if you are not - this is stuff every software developer should know) you should look at Leslie Lamport's Bakery Algorithm and go from there.






          share|improve this answer































            0














            You cannot implement it in C++. You have to use LOCK CMPXCHG. Here is my answer from here:



            ; BL is the mutex id
            ; shared_val, a memory address

            CMP [shared_val],BL ; Perhaps it is locked to us anyway
            JZ .OutLoop2
            .Loop1:
            CMP [shared_val],0xFF ; Free
            JZ .OutLoop1 ; Yes
            pause ; equal to rep nop.
            JMP .Loop1 ; Else, retry

            .OutLoop1:

            ; Lock is free, grab it
            MOV AL,0xFF
            LOCK CMPXCHG [shared_val],BL
            JNZ .Loop1 ; Write failed

            .OutLoop2: ; Lock Acquired





            share|improve this answer























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f14818915%2fsimplest-mutex-ever-does-this-example-work-is-it-thread-safe%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              7 Answers
              7






              active

              oldest

              votes








              7 Answers
              7






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              8















              Is it thread-safe?




              Certainly not. If a thread is preempted between checking and setting the lock, then a second thread could acquire that lock; if control then returns to the first thread, then both will acquire it. (And of course, on a modern processor, two or more cores could be executing the same instructions simultaneously for even more hilarity.)



              At the very least, you need an atomic test-and-set operation to implement a lock like this. The C++11 library provides such a thing:



              std::atomic_flag locked;

              if (!locked.test_and_set()) {
              vals.push_back(val);
              locked.clear();
              } else {
              // I don't know exactly what to do here;
              // but recursively calling add() is a very bad idea.
              }


              or better yet:



              std::mutex mutex;

              std::lock_guard<std::mutex> lock(mutex);
              vals.push_back(val);


              If you have an older implementation, then you'll have to rely on whatever extensions/libraries are available to you, as there was nothing helpful in the language or standard library back then.






              share|improve this answer


























              • hmmmmm. Thanks for the answers. I'm using VS2010 and g++, where the first one doesn't support mutex. Any other compiler independent idea?

                – The Quantum Physicist
                Feb 11 '13 at 19:42






              • 1





                @SamerAfach: The Boost.Thread and just::thread libraries have portable and (more or less) direct replacements for the C++11 mutex. Failing that there's the Windows API (critical sections, or whatever they call it); obviously that's not compiler-independent, so you'll need some carefully placed #defines to select which to use.

                – Mike Seymour
                Feb 11 '13 at 19:48













              • @MikeSymour if I use the boost Mutex for example (or any other Mutex), will that make the code thread-safe for other parallelization libraries, like OpenMPI and OpemMP? or does Mutex work exclusively for the parallelism of the library from which the Mutex is taken?

                – The Quantum Physicist
                Feb 12 '13 at 7:46






              • 1





                @SamerAfach: I don't quite understand the question, but I guess the answer is yes. Using a mutex correctly will serialise all sections of code that run with that mutex locked, making that code thread-safe, regardless of whatever parallelisation libraries you're using.

                – Mike Seymour
                Feb 14 '13 at 10:58











              • "regardless of whatever parallelisation libraries you're using". That answers my question. Thanks :)

                – The Quantum Physicist
                Feb 14 '13 at 11:03
















              8















              Is it thread-safe?




              Certainly not. If a thread is preempted between checking and setting the lock, then a second thread could acquire that lock; if control then returns to the first thread, then both will acquire it. (And of course, on a modern processor, two or more cores could be executing the same instructions simultaneously for even more hilarity.)



              At the very least, you need an atomic test-and-set operation to implement a lock like this. The C++11 library provides such a thing:



              std::atomic_flag locked;

              if (!locked.test_and_set()) {
              vals.push_back(val);
              locked.clear();
              } else {
              // I don't know exactly what to do here;
              // but recursively calling add() is a very bad idea.
              }


              or better yet:



              std::mutex mutex;

              std::lock_guard<std::mutex> lock(mutex);
              vals.push_back(val);


              If you have an older implementation, then you'll have to rely on whatever extensions/libraries are available to you, as there was nothing helpful in the language or standard library back then.






              share|improve this answer


























              • hmmmmm. Thanks for the answers. I'm using VS2010 and g++, where the first one doesn't support mutex. Any other compiler independent idea?

                – The Quantum Physicist
                Feb 11 '13 at 19:42






              • 1





                @SamerAfach: The Boost.Thread and just::thread libraries have portable and (more or less) direct replacements for the C++11 mutex. Failing that there's the Windows API (critical sections, or whatever they call it); obviously that's not compiler-independent, so you'll need some carefully placed #defines to select which to use.

                – Mike Seymour
                Feb 11 '13 at 19:48













              • @MikeSymour if I use the boost Mutex for example (or any other Mutex), will that make the code thread-safe for other parallelization libraries, like OpenMPI and OpemMP? or does Mutex work exclusively for the parallelism of the library from which the Mutex is taken?

                – The Quantum Physicist
                Feb 12 '13 at 7:46






              • 1





                @SamerAfach: I don't quite understand the question, but I guess the answer is yes. Using a mutex correctly will serialise all sections of code that run with that mutex locked, making that code thread-safe, regardless of whatever parallelisation libraries you're using.

                – Mike Seymour
                Feb 14 '13 at 10:58











              • "regardless of whatever parallelisation libraries you're using". That answers my question. Thanks :)

                – The Quantum Physicist
                Feb 14 '13 at 11:03














              8












              8








              8








              Is it thread-safe?




              Certainly not. If a thread is preempted between checking and setting the lock, then a second thread could acquire that lock; if control then returns to the first thread, then both will acquire it. (And of course, on a modern processor, two or more cores could be executing the same instructions simultaneously for even more hilarity.)



              At the very least, you need an atomic test-and-set operation to implement a lock like this. The C++11 library provides such a thing:



              std::atomic_flag locked;

              if (!locked.test_and_set()) {
              vals.push_back(val);
              locked.clear();
              } else {
              // I don't know exactly what to do here;
              // but recursively calling add() is a very bad idea.
              }


              or better yet:



              std::mutex mutex;

              std::lock_guard<std::mutex> lock(mutex);
              vals.push_back(val);


              If you have an older implementation, then you'll have to rely on whatever extensions/libraries are available to you, as there was nothing helpful in the language or standard library back then.






              share|improve this answer
















              Is it thread-safe?




              Certainly not. If a thread is preempted between checking and setting the lock, then a second thread could acquire that lock; if control then returns to the first thread, then both will acquire it. (And of course, on a modern processor, two or more cores could be executing the same instructions simultaneously for even more hilarity.)



              At the very least, you need an atomic test-and-set operation to implement a lock like this. The C++11 library provides such a thing:



              std::atomic_flag locked;

              if (!locked.test_and_set()) {
              vals.push_back(val);
              locked.clear();
              } else {
              // I don't know exactly what to do here;
              // but recursively calling add() is a very bad idea.
              }


              or better yet:



              std::mutex mutex;

              std::lock_guard<std::mutex> lock(mutex);
              vals.push_back(val);


              If you have an older implementation, then you'll have to rely on whatever extensions/libraries are available to you, as there was nothing helpful in the language or standard library back then.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Feb 11 '13 at 19:07

























              answered Feb 11 '13 at 19:00









              Mike SeymourMike Seymour

              216k19342558




              216k19342558













              • hmmmmm. Thanks for the answers. I'm using VS2010 and g++, where the first one doesn't support mutex. Any other compiler independent idea?

                – The Quantum Physicist
                Feb 11 '13 at 19:42






              • 1





                @SamerAfach: The Boost.Thread and just::thread libraries have portable and (more or less) direct replacements for the C++11 mutex. Failing that there's the Windows API (critical sections, or whatever they call it); obviously that's not compiler-independent, so you'll need some carefully placed #defines to select which to use.

                – Mike Seymour
                Feb 11 '13 at 19:48













              • @MikeSymour if I use the boost Mutex for example (or any other Mutex), will that make the code thread-safe for other parallelization libraries, like OpenMPI and OpemMP? or does Mutex work exclusively for the parallelism of the library from which the Mutex is taken?

                – The Quantum Physicist
                Feb 12 '13 at 7:46






              • 1





                @SamerAfach: I don't quite understand the question, but I guess the answer is yes. Using a mutex correctly will serialise all sections of code that run with that mutex locked, making that code thread-safe, regardless of whatever parallelisation libraries you're using.

                – Mike Seymour
                Feb 14 '13 at 10:58











              • "regardless of whatever parallelisation libraries you're using". That answers my question. Thanks :)

                – The Quantum Physicist
                Feb 14 '13 at 11:03



















              • hmmmmm. Thanks for the answers. I'm using VS2010 and g++, where the first one doesn't support mutex. Any other compiler independent idea?

                – The Quantum Physicist
                Feb 11 '13 at 19:42






              • 1





                @SamerAfach: The Boost.Thread and just::thread libraries have portable and (more or less) direct replacements for the C++11 mutex. Failing that there's the Windows API (critical sections, or whatever they call it); obviously that's not compiler-independent, so you'll need some carefully placed #defines to select which to use.

                – Mike Seymour
                Feb 11 '13 at 19:48













              • @MikeSymour if I use the boost Mutex for example (or any other Mutex), will that make the code thread-safe for other parallelization libraries, like OpenMPI and OpemMP? or does Mutex work exclusively for the parallelism of the library from which the Mutex is taken?

                – The Quantum Physicist
                Feb 12 '13 at 7:46






              • 1





                @SamerAfach: I don't quite understand the question, but I guess the answer is yes. Using a mutex correctly will serialise all sections of code that run with that mutex locked, making that code thread-safe, regardless of whatever parallelisation libraries you're using.

                – Mike Seymour
                Feb 14 '13 at 10:58











              • "regardless of whatever parallelisation libraries you're using". That answers my question. Thanks :)

                – The Quantum Physicist
                Feb 14 '13 at 11:03

















              hmmmmm. Thanks for the answers. I'm using VS2010 and g++, where the first one doesn't support mutex. Any other compiler independent idea?

              – The Quantum Physicist
              Feb 11 '13 at 19:42





              hmmmmm. Thanks for the answers. I'm using VS2010 and g++, where the first one doesn't support mutex. Any other compiler independent idea?

              – The Quantum Physicist
              Feb 11 '13 at 19:42




              1




              1





              @SamerAfach: The Boost.Thread and just::thread libraries have portable and (more or less) direct replacements for the C++11 mutex. Failing that there's the Windows API (critical sections, or whatever they call it); obviously that's not compiler-independent, so you'll need some carefully placed #defines to select which to use.

              – Mike Seymour
              Feb 11 '13 at 19:48







              @SamerAfach: The Boost.Thread and just::thread libraries have portable and (more or less) direct replacements for the C++11 mutex. Failing that there's the Windows API (critical sections, or whatever they call it); obviously that's not compiler-independent, so you'll need some carefully placed #defines to select which to use.

              – Mike Seymour
              Feb 11 '13 at 19:48















              @MikeSymour if I use the boost Mutex for example (or any other Mutex), will that make the code thread-safe for other parallelization libraries, like OpenMPI and OpemMP? or does Mutex work exclusively for the parallelism of the library from which the Mutex is taken?

              – The Quantum Physicist
              Feb 12 '13 at 7:46





              @MikeSymour if I use the boost Mutex for example (or any other Mutex), will that make the code thread-safe for other parallelization libraries, like OpenMPI and OpemMP? or does Mutex work exclusively for the parallelism of the library from which the Mutex is taken?

              – The Quantum Physicist
              Feb 12 '13 at 7:46




              1




              1





              @SamerAfach: I don't quite understand the question, but I guess the answer is yes. Using a mutex correctly will serialise all sections of code that run with that mutex locked, making that code thread-safe, regardless of whatever parallelisation libraries you're using.

              – Mike Seymour
              Feb 14 '13 at 10:58





              @SamerAfach: I don't quite understand the question, but I guess the answer is yes. Using a mutex correctly will serialise all sections of code that run with that mutex locked, making that code thread-safe, regardless of whatever parallelisation libraries you're using.

              – Mike Seymour
              Feb 14 '13 at 10:58













              "regardless of whatever parallelisation libraries you're using". That answers my question. Thanks :)

              – The Quantum Physicist
              Feb 14 '13 at 11:03





              "regardless of whatever parallelisation libraries you're using". That answers my question. Thanks :)

              – The Quantum Physicist
              Feb 14 '13 at 11:03













              5














              No, this is not thread safe. There's a race between



              if(!locked)


              and



              this->locked = 1;


              If there is a context switch between these two statements, your lock mechanism falls apart. You need an atomic test and set instruction, or simply use an existing mutex.






              share|improve this answer




























                5














                No, this is not thread safe. There's a race between



                if(!locked)


                and



                this->locked = 1;


                If there is a context switch between these two statements, your lock mechanism falls apart. You need an atomic test and set instruction, or simply use an existing mutex.






                share|improve this answer


























                  5












                  5








                  5







                  No, this is not thread safe. There's a race between



                  if(!locked)


                  and



                  this->locked = 1;


                  If there is a context switch between these two statements, your lock mechanism falls apart. You need an atomic test and set instruction, or simply use an existing mutex.






                  share|improve this answer













                  No, this is not thread safe. There's a race between



                  if(!locked)


                  and



                  this->locked = 1;


                  If there is a context switch between these two statements, your lock mechanism falls apart. You need an atomic test and set instruction, or simply use an existing mutex.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Feb 11 '13 at 18:59









                  Olaf DietscheOlaf Dietsche

                  56.9k565144




                  56.9k565144























                      5














                      This code doesn't provide an atomic modification of vals vector. Consider the following scenario:



                      //<<< Suppose it's 0
                      if(!locked)
                      { //<<< Thread 0 passes the check
                      //<<< Context Switch - and Thread 1 is also there because locked is 0
                      this->locked = 1;
                      //<<< Now it's possible for one thread to be scheduled when another one is in
                      //<<< the middle of modification of the vector
                      this->vals.push_back(val);
                      this->locked = 0;
                      }





                      share|improve this answer




























                        5














                        This code doesn't provide an atomic modification of vals vector. Consider the following scenario:



                        //<<< Suppose it's 0
                        if(!locked)
                        { //<<< Thread 0 passes the check
                        //<<< Context Switch - and Thread 1 is also there because locked is 0
                        this->locked = 1;
                        //<<< Now it's possible for one thread to be scheduled when another one is in
                        //<<< the middle of modification of the vector
                        this->vals.push_back(val);
                        this->locked = 0;
                        }





                        share|improve this answer


























                          5












                          5








                          5







                          This code doesn't provide an atomic modification of vals vector. Consider the following scenario:



                          //<<< Suppose it's 0
                          if(!locked)
                          { //<<< Thread 0 passes the check
                          //<<< Context Switch - and Thread 1 is also there because locked is 0
                          this->locked = 1;
                          //<<< Now it's possible for one thread to be scheduled when another one is in
                          //<<< the middle of modification of the vector
                          this->vals.push_back(val);
                          this->locked = 0;
                          }





                          share|improve this answer













                          This code doesn't provide an atomic modification of vals vector. Consider the following scenario:



                          //<<< Suppose it's 0
                          if(!locked)
                          { //<<< Thread 0 passes the check
                          //<<< Context Switch - and Thread 1 is also there because locked is 0
                          this->locked = 1;
                          //<<< Now it's possible for one thread to be scheduled when another one is in
                          //<<< the middle of modification of the vector
                          this->vals.push_back(val);
                          this->locked = 0;
                          }






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Feb 11 '13 at 19:03









                          Maksim SkurydzinMaksim Skurydzin

                          7,49663149




                          7,49663149























                              2















                              Does this work? Is it thread-safe?




                              No. It will fail at times.



                              Your mutex will only work if other threads never do anything between the execution of these two lines:



                              if(!locked)
                              {
                              this->locked = 1;


                              ...and you have not ensured that.



                              To learn about the how of mutex writing, see this SO post.






                              share|improve this answer






























                                2















                                Does this work? Is it thread-safe?




                                No. It will fail at times.



                                Your mutex will only work if other threads never do anything between the execution of these two lines:



                                if(!locked)
                                {
                                this->locked = 1;


                                ...and you have not ensured that.



                                To learn about the how of mutex writing, see this SO post.






                                share|improve this answer




























                                  2












                                  2








                                  2








                                  Does this work? Is it thread-safe?




                                  No. It will fail at times.



                                  Your mutex will only work if other threads never do anything between the execution of these two lines:



                                  if(!locked)
                                  {
                                  this->locked = 1;


                                  ...and you have not ensured that.



                                  To learn about the how of mutex writing, see this SO post.






                                  share|improve this answer
















                                  Does this work? Is it thread-safe?




                                  No. It will fail at times.



                                  Your mutex will only work if other threads never do anything between the execution of these two lines:



                                  if(!locked)
                                  {
                                  this->locked = 1;


                                  ...and you have not ensured that.



                                  To learn about the how of mutex writing, see this SO post.







                                  share|improve this answer














                                  share|improve this answer



                                  share|improve this answer








                                  edited May 23 '17 at 11:48









                                  Community

                                  11




                                  11










                                  answered Feb 11 '13 at 18:58









                                  Drew DormannDrew Dormann

                                  41.9k979142




                                  41.9k979142























                                      2














                                      No, that is not thread safe.



                                      Consider two threads running myclass::add at more-or-less the same time. Also, imagine that the value of .locked is false.



                                      The first thread executes up to and including this line:



                                      if(!locked)
                                      {


                                      Now imagine that the system switches context to the second thread. It also executes up to the same line.



                                      Now we have two different threads, both believing that they have exclusive access, and both inside the !locked condition of the if.



                                      They will both call vals.push_back() at more-or-less the same time.



                                      Boom.






                                      share|improve this answer




























                                        2














                                        No, that is not thread safe.



                                        Consider two threads running myclass::add at more-or-less the same time. Also, imagine that the value of .locked is false.



                                        The first thread executes up to and including this line:



                                        if(!locked)
                                        {


                                        Now imagine that the system switches context to the second thread. It also executes up to the same line.



                                        Now we have two different threads, both believing that they have exclusive access, and both inside the !locked condition of the if.



                                        They will both call vals.push_back() at more-or-less the same time.



                                        Boom.






                                        share|improve this answer


























                                          2












                                          2








                                          2







                                          No, that is not thread safe.



                                          Consider two threads running myclass::add at more-or-less the same time. Also, imagine that the value of .locked is false.



                                          The first thread executes up to and including this line:



                                          if(!locked)
                                          {


                                          Now imagine that the system switches context to the second thread. It also executes up to the same line.



                                          Now we have two different threads, both believing that they have exclusive access, and both inside the !locked condition of the if.



                                          They will both call vals.push_back() at more-or-less the same time.



                                          Boom.






                                          share|improve this answer













                                          No, that is not thread safe.



                                          Consider two threads running myclass::add at more-or-less the same time. Also, imagine that the value of .locked is false.



                                          The first thread executes up to and including this line:



                                          if(!locked)
                                          {


                                          Now imagine that the system switches context to the second thread. It also executes up to the same line.



                                          Now we have two different threads, both believing that they have exclusive access, and both inside the !locked condition of the if.



                                          They will both call vals.push_back() at more-or-less the same time.



                                          Boom.







                                          share|improve this answer












                                          share|improve this answer



                                          share|improve this answer










                                          answered Feb 11 '13 at 18:59









                                          RobᵩRobᵩ

                                          117k13140222




                                          117k13140222























                                              1














                                              Others have already shown how your mutex can fail, so I won't rehash their points. I will only add one thing: The simplest mutex implementation is a lot more complicated than your code.



                                              If you're interested in the nitty gritty (or even if you are not - this is stuff every software developer should know) you should look at Leslie Lamport's Bakery Algorithm and go from there.






                                              share|improve this answer




























                                                1














                                                Others have already shown how your mutex can fail, so I won't rehash their points. I will only add one thing: The simplest mutex implementation is a lot more complicated than your code.



                                                If you're interested in the nitty gritty (or even if you are not - this is stuff every software developer should know) you should look at Leslie Lamport's Bakery Algorithm and go from there.






                                                share|improve this answer


























                                                  1












                                                  1








                                                  1







                                                  Others have already shown how your mutex can fail, so I won't rehash their points. I will only add one thing: The simplest mutex implementation is a lot more complicated than your code.



                                                  If you're interested in the nitty gritty (or even if you are not - this is stuff every software developer should know) you should look at Leslie Lamport's Bakery Algorithm and go from there.






                                                  share|improve this answer













                                                  Others have already shown how your mutex can fail, so I won't rehash their points. I will only add one thing: The simplest mutex implementation is a lot more complicated than your code.



                                                  If you're interested in the nitty gritty (or even if you are not - this is stuff every software developer should know) you should look at Leslie Lamport's Bakery Algorithm and go from there.







                                                  share|improve this answer












                                                  share|improve this answer



                                                  share|improve this answer










                                                  answered Feb 11 '13 at 19:05









                                                  Nik BougalisNik Bougalis

                                                  9,71211734




                                                  9,71211734























                                                      0














                                                      You cannot implement it in C++. You have to use LOCK CMPXCHG. Here is my answer from here:



                                                      ; BL is the mutex id
                                                      ; shared_val, a memory address

                                                      CMP [shared_val],BL ; Perhaps it is locked to us anyway
                                                      JZ .OutLoop2
                                                      .Loop1:
                                                      CMP [shared_val],0xFF ; Free
                                                      JZ .OutLoop1 ; Yes
                                                      pause ; equal to rep nop.
                                                      JMP .Loop1 ; Else, retry

                                                      .OutLoop1:

                                                      ; Lock is free, grab it
                                                      MOV AL,0xFF
                                                      LOCK CMPXCHG [shared_val],BL
                                                      JNZ .Loop1 ; Write failed

                                                      .OutLoop2: ; Lock Acquired





                                                      share|improve this answer




























                                                        0














                                                        You cannot implement it in C++. You have to use LOCK CMPXCHG. Here is my answer from here:



                                                        ; BL is the mutex id
                                                        ; shared_val, a memory address

                                                        CMP [shared_val],BL ; Perhaps it is locked to us anyway
                                                        JZ .OutLoop2
                                                        .Loop1:
                                                        CMP [shared_val],0xFF ; Free
                                                        JZ .OutLoop1 ; Yes
                                                        pause ; equal to rep nop.
                                                        JMP .Loop1 ; Else, retry

                                                        .OutLoop1:

                                                        ; Lock is free, grab it
                                                        MOV AL,0xFF
                                                        LOCK CMPXCHG [shared_val],BL
                                                        JNZ .Loop1 ; Write failed

                                                        .OutLoop2: ; Lock Acquired





                                                        share|improve this answer


























                                                          0












                                                          0








                                                          0







                                                          You cannot implement it in C++. You have to use LOCK CMPXCHG. Here is my answer from here:



                                                          ; BL is the mutex id
                                                          ; shared_val, a memory address

                                                          CMP [shared_val],BL ; Perhaps it is locked to us anyway
                                                          JZ .OutLoop2
                                                          .Loop1:
                                                          CMP [shared_val],0xFF ; Free
                                                          JZ .OutLoop1 ; Yes
                                                          pause ; equal to rep nop.
                                                          JMP .Loop1 ; Else, retry

                                                          .OutLoop1:

                                                          ; Lock is free, grab it
                                                          MOV AL,0xFF
                                                          LOCK CMPXCHG [shared_val],BL
                                                          JNZ .Loop1 ; Write failed

                                                          .OutLoop2: ; Lock Acquired





                                                          share|improve this answer













                                                          You cannot implement it in C++. You have to use LOCK CMPXCHG. Here is my answer from here:



                                                          ; BL is the mutex id
                                                          ; shared_val, a memory address

                                                          CMP [shared_val],BL ; Perhaps it is locked to us anyway
                                                          JZ .OutLoop2
                                                          .Loop1:
                                                          CMP [shared_val],0xFF ; Free
                                                          JZ .OutLoop1 ; Yes
                                                          pause ; equal to rep nop.
                                                          JMP .Loop1 ; Else, retry

                                                          .OutLoop1:

                                                          ; Lock is free, grab it
                                                          MOV AL,0xFF
                                                          LOCK CMPXCHG [shared_val],BL
                                                          JNZ .Loop1 ; Write failed

                                                          .OutLoop2: ; Lock Acquired






                                                          share|improve this answer












                                                          share|improve this answer



                                                          share|improve this answer










                                                          answered Jan 2 at 9:09









                                                          MichaelMichael

                                                          1,4591836




                                                          1,4591836






























                                                              draft saved

                                                              draft discarded




















































                                                              Thanks for contributing an answer to Stack Overflow!


                                                              • Please be sure to answer the question. Provide details and share your research!

                                                              But avoid



                                                              • Asking for help, clarification, or responding to other answers.

                                                              • Making statements based on opinion; back them up with references or personal experience.


                                                              To learn more, see our tips on writing great answers.




                                                              draft saved


                                                              draft discarded














                                                              StackExchange.ready(
                                                              function () {
                                                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f14818915%2fsimplest-mutex-ever-does-this-example-work-is-it-thread-safe%23new-answer', 'question_page');
                                                              }
                                                              );

                                                              Post as a guest















                                                              Required, but never shown





















































                                                              Required, but never shown














                                                              Required, but never shown












                                                              Required, but never shown







                                                              Required, but never shown

































                                                              Required, but never shown














                                                              Required, but never shown












                                                              Required, but never shown







                                                              Required, but never shown







                                                              Popular posts from this blog

                                                              Monofisismo

                                                              Angular Downloading a file using contenturl with Basic Authentication

                                                              Olmecas