Including std::lock_guard in extra scope












28















Does is make sense to do something like putting a std::lock_guard in an extra scope so that the locking period is as short as possible?



Pseudo code:



// all used variables beside the lock_guard are created and initialized somewhere else
...// do something

{ // open new scope
std::lock_guard<std::mutex> lock(mut);
shared_var = newValue;
} // close the scope

... // do some other stuff (that might take longer)


Are there more advantages besides having a short lock duration?



What might be negative side effects?










share|improve this question





























    28















    Does is make sense to do something like putting a std::lock_guard in an extra scope so that the locking period is as short as possible?



    Pseudo code:



    // all used variables beside the lock_guard are created and initialized somewhere else
    ...// do something

    { // open new scope
    std::lock_guard<std::mutex> lock(mut);
    shared_var = newValue;
    } // close the scope

    ... // do some other stuff (that might take longer)


    Are there more advantages besides having a short lock duration?



    What might be negative side effects?










    share|improve this question



























      28












      28








      28


      1






      Does is make sense to do something like putting a std::lock_guard in an extra scope so that the locking period is as short as possible?



      Pseudo code:



      // all used variables beside the lock_guard are created and initialized somewhere else
      ...// do something

      { // open new scope
      std::lock_guard<std::mutex> lock(mut);
      shared_var = newValue;
      } // close the scope

      ... // do some other stuff (that might take longer)


      Are there more advantages besides having a short lock duration?



      What might be negative side effects?










      share|improve this question
















      Does is make sense to do something like putting a std::lock_guard in an extra scope so that the locking period is as short as possible?



      Pseudo code:



      // all used variables beside the lock_guard are created and initialized somewhere else
      ...// do something

      { // open new scope
      std::lock_guard<std::mutex> lock(mut);
      shared_var = newValue;
      } // close the scope

      ... // do some other stuff (that might take longer)


      Are there more advantages besides having a short lock duration?



      What might be negative side effects?







      c++ locking mutex






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 28 at 10:21









      Angew

      134k11258351




      134k11258351










      asked Jan 28 at 10:13









      KabCodeKabCode

      333314




      333314
























          5 Answers
          5






          active

          oldest

          votes


















          26














          Yes, it certainly makes sense to limit the scope of lock guards to be as short as possible, but not shorter.



          The longer you hold a lock, the more likely it is that a thread will block waiting for that lock, which impacts performance as is thus usually considered a bad thing.



          However, you must make sure that the program is still correct and that the lock is held at all times when it must be, i.e. when the shared resource protected by the lock is accessed or modified.



          There may be one more point to consider (I do not have enough practical experience here to speak with certainty). Locking/releasing a mutex can potentially be an operation with nontrivial performance costs itself. Therefore, it may turn out that keeping a lock for a slightly longer period instead of unlocking & re-locking it several times in the course of one operation can actually improve overall performace. This is something which profiling could show you.






          share|improve this answer































            12














            There might be a disadvantage: you cannot protect initializations this way. For example:



            {
            std::lock_guard<std::mutex> lock(mut);
            Some_resource var{shared_var};
            } // woops! var is lost


            You have to use assignment like this:



            Some_resource var;
            {
            std::lock_guard<std::mutex> lock(mut);
            var = shared_Var;
            }


            Which can be not as good, you know, since for some types, dummy initialization (I intentionally avoided the term "default initialization") and then assignment is less efficient than directly initialization. (I intentionally avoided the term "direct initialization") Furthermore, in some situations, you cannot change the variable after initialization. (e.g. const ones)





            @P i pointed out this solution:



            // use an immediately-invoked temporary lambda
            Some_resource var {
            [&] {
            std::lock_guard<std::mutex> lock(mut);
            return shared_var;
            } () // parentheses for invoke
            };


            This way, with return value optimization, which is implemented well and properly by almost all popular modern compilers, and which is mandated as of C++17, you can do exactly what is expected.






            share|improve this answer





















            • 1





              Hi, what's wrong? I am willing to improve :)

              – L. F.
              Jan 28 at 10:28






            • 3





              You could use immediately invoked lambda

              – user32434999
              Jan 28 at 10:31






            • 1





              @KabCode It is as the scope is only due to the scheme mentioned in the question

              – user32434999
              Jan 28 at 10:33






            • 2





              Some_resource var{ [&]() { std::lock_guard<std::mutex> lock(mut); return shared_var; }() };

              – user32434999
              Jan 28 at 10:43








            • 1





              @L.F. I also think shared_var deserves a const

              – user32434999
              Jan 28 at 10:49





















            1














            Yes, it makes sense.



            There are no other advantages, and there are no side-effects (it is a good way to write it).



            An even better way, is to extract it into a private member function (if you have an operation that is synchronized this way, you might as well give the operation its own name):



            {
            // all used variables beside the lock_guard are created and initialized somewhere else
            ...// do something

            set_var(new_value);

            ... // do some other stuff (that might take longer)
            }

            void your_class::set_value(int new_value)
            {
            std::lock_guard<std::mutex> lock(mut);
            shared_var = new_value;
            }





            share|improve this answer
























            • Good addition. This will help to keep the code clean. Caveat might be if you have to set this variable often then the costs of creating new locks might be more expensive than lock/unlock (but this is not the scope of the question anymore).

              – KabCode
              Jan 28 at 10:28











            • @KabCode why would you set the value often? Each thread should minimize access to shared memory. When writing several times you should write only the last value, unless other threads are supposed to see the intermediate values, but then you have no choice other than locking for each write

              – user463035818
              Jan 28 at 11:09













            • @KabCode ah I think now I got what you wanted to say. You are worried by the overhead of creating a new lock instead of reusing the object (?). In that case I suggest you to take a look at the implementation, the lock isnt really doing much, it merely locks the mutex and realeases it, there is not much overhead

              – user463035818
              Jan 28 at 11:11





















            1














            Using an extra scope specifically to limit the lifetime of an std::lock_guard object is indeed good practice. As the other answers point out, locking your mutex for the shortest period of time will reduce the chances that another thread will block on the mutex.



            I see one more point that was not mentioned in the other answers: transactional operations. Let's use the classical example of a money transfer between two bank accounts. For your banking program to be correct, the modification of the two bank account's balance must be done without unlocking the mutex in between. Otherwise, it would be possible for another thread to lock the mutex while the program is in a weird state where only one of the accounts was credited/debited while the other account's balance was untouched!



            With this in mind, it is not enough to ensure that the mutex is locked when each shared resource is modified. Sometimes, you must keep the mutex locked for a period of time spanning the modification of all the shared resources that form a transaction.



            EDIT:



            If for some reason keeping the mutex locked for the whole duration of the transaction is not acceptable, you can use the following algorithm:

            1. Lock mutex, read input data, unlock mutex.

            2. Perform all needed computations, save results locally.

            3. Lock mutex, check that input data has not changed, perform the transaction with readily available results, unlock the mutex.



            If the input data has changed during the execution of step 2, throw away the results and start over with the fresh input data.






            share|improve this answer


























            • Good point - could you provide a (pseudo)code sample how you would solve this issue programmatically?

              – KabCode
              Jan 29 at 8:29



















            -1














            I don't see the reason to do it.
            If you do something so simple as "set one variable" - use atomic<> and you don't need mutex and lock at all. If you do something complicated - extract this code into new function and use lock in its first line.






            share|improve this answer
























            • But it is not always worth it to extract into a new function, right?

              – L. F.
              Jan 29 at 11:16











            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%2f54399719%2fincluding-stdlock-guard-in-extra-scope%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            5 Answers
            5






            active

            oldest

            votes








            5 Answers
            5






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            26














            Yes, it certainly makes sense to limit the scope of lock guards to be as short as possible, but not shorter.



            The longer you hold a lock, the more likely it is that a thread will block waiting for that lock, which impacts performance as is thus usually considered a bad thing.



            However, you must make sure that the program is still correct and that the lock is held at all times when it must be, i.e. when the shared resource protected by the lock is accessed or modified.



            There may be one more point to consider (I do not have enough practical experience here to speak with certainty). Locking/releasing a mutex can potentially be an operation with nontrivial performance costs itself. Therefore, it may turn out that keeping a lock for a slightly longer period instead of unlocking & re-locking it several times in the course of one operation can actually improve overall performace. This is something which profiling could show you.






            share|improve this answer




























              26














              Yes, it certainly makes sense to limit the scope of lock guards to be as short as possible, but not shorter.



              The longer you hold a lock, the more likely it is that a thread will block waiting for that lock, which impacts performance as is thus usually considered a bad thing.



              However, you must make sure that the program is still correct and that the lock is held at all times when it must be, i.e. when the shared resource protected by the lock is accessed or modified.



              There may be one more point to consider (I do not have enough practical experience here to speak with certainty). Locking/releasing a mutex can potentially be an operation with nontrivial performance costs itself. Therefore, it may turn out that keeping a lock for a slightly longer period instead of unlocking & re-locking it several times in the course of one operation can actually improve overall performace. This is something which profiling could show you.






              share|improve this answer


























                26












                26








                26







                Yes, it certainly makes sense to limit the scope of lock guards to be as short as possible, but not shorter.



                The longer you hold a lock, the more likely it is that a thread will block waiting for that lock, which impacts performance as is thus usually considered a bad thing.



                However, you must make sure that the program is still correct and that the lock is held at all times when it must be, i.e. when the shared resource protected by the lock is accessed or modified.



                There may be one more point to consider (I do not have enough practical experience here to speak with certainty). Locking/releasing a mutex can potentially be an operation with nontrivial performance costs itself. Therefore, it may turn out that keeping a lock for a slightly longer period instead of unlocking & re-locking it several times in the course of one operation can actually improve overall performace. This is something which profiling could show you.






                share|improve this answer













                Yes, it certainly makes sense to limit the scope of lock guards to be as short as possible, but not shorter.



                The longer you hold a lock, the more likely it is that a thread will block waiting for that lock, which impacts performance as is thus usually considered a bad thing.



                However, you must make sure that the program is still correct and that the lock is held at all times when it must be, i.e. when the shared resource protected by the lock is accessed or modified.



                There may be one more point to consider (I do not have enough practical experience here to speak with certainty). Locking/releasing a mutex can potentially be an operation with nontrivial performance costs itself. Therefore, it may turn out that keeping a lock for a slightly longer period instead of unlocking & re-locking it several times in the course of one operation can actually improve overall performace. This is something which profiling could show you.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 28 at 10:17









                AngewAngew

                134k11258351




                134k11258351

























                    12














                    There might be a disadvantage: you cannot protect initializations this way. For example:



                    {
                    std::lock_guard<std::mutex> lock(mut);
                    Some_resource var{shared_var};
                    } // woops! var is lost


                    You have to use assignment like this:



                    Some_resource var;
                    {
                    std::lock_guard<std::mutex> lock(mut);
                    var = shared_Var;
                    }


                    Which can be not as good, you know, since for some types, dummy initialization (I intentionally avoided the term "default initialization") and then assignment is less efficient than directly initialization. (I intentionally avoided the term "direct initialization") Furthermore, in some situations, you cannot change the variable after initialization. (e.g. const ones)





                    @P i pointed out this solution:



                    // use an immediately-invoked temporary lambda
                    Some_resource var {
                    [&] {
                    std::lock_guard<std::mutex> lock(mut);
                    return shared_var;
                    } () // parentheses for invoke
                    };


                    This way, with return value optimization, which is implemented well and properly by almost all popular modern compilers, and which is mandated as of C++17, you can do exactly what is expected.






                    share|improve this answer





















                    • 1





                      Hi, what's wrong? I am willing to improve :)

                      – L. F.
                      Jan 28 at 10:28






                    • 3





                      You could use immediately invoked lambda

                      – user32434999
                      Jan 28 at 10:31






                    • 1





                      @KabCode It is as the scope is only due to the scheme mentioned in the question

                      – user32434999
                      Jan 28 at 10:33






                    • 2





                      Some_resource var{ [&]() { std::lock_guard<std::mutex> lock(mut); return shared_var; }() };

                      – user32434999
                      Jan 28 at 10:43








                    • 1





                      @L.F. I also think shared_var deserves a const

                      – user32434999
                      Jan 28 at 10:49


















                    12














                    There might be a disadvantage: you cannot protect initializations this way. For example:



                    {
                    std::lock_guard<std::mutex> lock(mut);
                    Some_resource var{shared_var};
                    } // woops! var is lost


                    You have to use assignment like this:



                    Some_resource var;
                    {
                    std::lock_guard<std::mutex> lock(mut);
                    var = shared_Var;
                    }


                    Which can be not as good, you know, since for some types, dummy initialization (I intentionally avoided the term "default initialization") and then assignment is less efficient than directly initialization. (I intentionally avoided the term "direct initialization") Furthermore, in some situations, you cannot change the variable after initialization. (e.g. const ones)





                    @P i pointed out this solution:



                    // use an immediately-invoked temporary lambda
                    Some_resource var {
                    [&] {
                    std::lock_guard<std::mutex> lock(mut);
                    return shared_var;
                    } () // parentheses for invoke
                    };


                    This way, with return value optimization, which is implemented well and properly by almost all popular modern compilers, and which is mandated as of C++17, you can do exactly what is expected.






                    share|improve this answer





















                    • 1





                      Hi, what's wrong? I am willing to improve :)

                      – L. F.
                      Jan 28 at 10:28






                    • 3





                      You could use immediately invoked lambda

                      – user32434999
                      Jan 28 at 10:31






                    • 1





                      @KabCode It is as the scope is only due to the scheme mentioned in the question

                      – user32434999
                      Jan 28 at 10:33






                    • 2





                      Some_resource var{ [&]() { std::lock_guard<std::mutex> lock(mut); return shared_var; }() };

                      – user32434999
                      Jan 28 at 10:43








                    • 1





                      @L.F. I also think shared_var deserves a const

                      – user32434999
                      Jan 28 at 10:49
















                    12












                    12








                    12







                    There might be a disadvantage: you cannot protect initializations this way. For example:



                    {
                    std::lock_guard<std::mutex> lock(mut);
                    Some_resource var{shared_var};
                    } // woops! var is lost


                    You have to use assignment like this:



                    Some_resource var;
                    {
                    std::lock_guard<std::mutex> lock(mut);
                    var = shared_Var;
                    }


                    Which can be not as good, you know, since for some types, dummy initialization (I intentionally avoided the term "default initialization") and then assignment is less efficient than directly initialization. (I intentionally avoided the term "direct initialization") Furthermore, in some situations, you cannot change the variable after initialization. (e.g. const ones)





                    @P i pointed out this solution:



                    // use an immediately-invoked temporary lambda
                    Some_resource var {
                    [&] {
                    std::lock_guard<std::mutex> lock(mut);
                    return shared_var;
                    } () // parentheses for invoke
                    };


                    This way, with return value optimization, which is implemented well and properly by almost all popular modern compilers, and which is mandated as of C++17, you can do exactly what is expected.






                    share|improve this answer















                    There might be a disadvantage: you cannot protect initializations this way. For example:



                    {
                    std::lock_guard<std::mutex> lock(mut);
                    Some_resource var{shared_var};
                    } // woops! var is lost


                    You have to use assignment like this:



                    Some_resource var;
                    {
                    std::lock_guard<std::mutex> lock(mut);
                    var = shared_Var;
                    }


                    Which can be not as good, you know, since for some types, dummy initialization (I intentionally avoided the term "default initialization") and then assignment is less efficient than directly initialization. (I intentionally avoided the term "direct initialization") Furthermore, in some situations, you cannot change the variable after initialization. (e.g. const ones)





                    @P i pointed out this solution:



                    // use an immediately-invoked temporary lambda
                    Some_resource var {
                    [&] {
                    std::lock_guard<std::mutex> lock(mut);
                    return shared_var;
                    } () // parentheses for invoke
                    };


                    This way, with return value optimization, which is implemented well and properly by almost all popular modern compilers, and which is mandated as of C++17, you can do exactly what is expected.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Jan 29 at 5:51

























                    answered Jan 28 at 10:27









                    L. F.L. F.

                    1,194418




                    1,194418








                    • 1





                      Hi, what's wrong? I am willing to improve :)

                      – L. F.
                      Jan 28 at 10:28






                    • 3





                      You could use immediately invoked lambda

                      – user32434999
                      Jan 28 at 10:31






                    • 1





                      @KabCode It is as the scope is only due to the scheme mentioned in the question

                      – user32434999
                      Jan 28 at 10:33






                    • 2





                      Some_resource var{ [&]() { std::lock_guard<std::mutex> lock(mut); return shared_var; }() };

                      – user32434999
                      Jan 28 at 10:43








                    • 1





                      @L.F. I also think shared_var deserves a const

                      – user32434999
                      Jan 28 at 10:49
















                    • 1





                      Hi, what's wrong? I am willing to improve :)

                      – L. F.
                      Jan 28 at 10:28






                    • 3





                      You could use immediately invoked lambda

                      – user32434999
                      Jan 28 at 10:31






                    • 1





                      @KabCode It is as the scope is only due to the scheme mentioned in the question

                      – user32434999
                      Jan 28 at 10:33






                    • 2





                      Some_resource var{ [&]() { std::lock_guard<std::mutex> lock(mut); return shared_var; }() };

                      – user32434999
                      Jan 28 at 10:43








                    • 1





                      @L.F. I also think shared_var deserves a const

                      – user32434999
                      Jan 28 at 10:49










                    1




                    1





                    Hi, what's wrong? I am willing to improve :)

                    – L. F.
                    Jan 28 at 10:28





                    Hi, what's wrong? I am willing to improve :)

                    – L. F.
                    Jan 28 at 10:28




                    3




                    3





                    You could use immediately invoked lambda

                    – user32434999
                    Jan 28 at 10:31





                    You could use immediately invoked lambda

                    – user32434999
                    Jan 28 at 10:31




                    1




                    1





                    @KabCode It is as the scope is only due to the scheme mentioned in the question

                    – user32434999
                    Jan 28 at 10:33





                    @KabCode It is as the scope is only due to the scheme mentioned in the question

                    – user32434999
                    Jan 28 at 10:33




                    2




                    2





                    Some_resource var{ [&]() { std::lock_guard<std::mutex> lock(mut); return shared_var; }() };

                    – user32434999
                    Jan 28 at 10:43







                    Some_resource var{ [&]() { std::lock_guard<std::mutex> lock(mut); return shared_var; }() };

                    – user32434999
                    Jan 28 at 10:43






                    1




                    1





                    @L.F. I also think shared_var deserves a const

                    – user32434999
                    Jan 28 at 10:49







                    @L.F. I also think shared_var deserves a const

                    – user32434999
                    Jan 28 at 10:49













                    1














                    Yes, it makes sense.



                    There are no other advantages, and there are no side-effects (it is a good way to write it).



                    An even better way, is to extract it into a private member function (if you have an operation that is synchronized this way, you might as well give the operation its own name):



                    {
                    // all used variables beside the lock_guard are created and initialized somewhere else
                    ...// do something

                    set_var(new_value);

                    ... // do some other stuff (that might take longer)
                    }

                    void your_class::set_value(int new_value)
                    {
                    std::lock_guard<std::mutex> lock(mut);
                    shared_var = new_value;
                    }





                    share|improve this answer
























                    • Good addition. This will help to keep the code clean. Caveat might be if you have to set this variable often then the costs of creating new locks might be more expensive than lock/unlock (but this is not the scope of the question anymore).

                      – KabCode
                      Jan 28 at 10:28











                    • @KabCode why would you set the value often? Each thread should minimize access to shared memory. When writing several times you should write only the last value, unless other threads are supposed to see the intermediate values, but then you have no choice other than locking for each write

                      – user463035818
                      Jan 28 at 11:09













                    • @KabCode ah I think now I got what you wanted to say. You are worried by the overhead of creating a new lock instead of reusing the object (?). In that case I suggest you to take a look at the implementation, the lock isnt really doing much, it merely locks the mutex and realeases it, there is not much overhead

                      – user463035818
                      Jan 28 at 11:11


















                    1














                    Yes, it makes sense.



                    There are no other advantages, and there are no side-effects (it is a good way to write it).



                    An even better way, is to extract it into a private member function (if you have an operation that is synchronized this way, you might as well give the operation its own name):



                    {
                    // all used variables beside the lock_guard are created and initialized somewhere else
                    ...// do something

                    set_var(new_value);

                    ... // do some other stuff (that might take longer)
                    }

                    void your_class::set_value(int new_value)
                    {
                    std::lock_guard<std::mutex> lock(mut);
                    shared_var = new_value;
                    }





                    share|improve this answer
























                    • Good addition. This will help to keep the code clean. Caveat might be if you have to set this variable often then the costs of creating new locks might be more expensive than lock/unlock (but this is not the scope of the question anymore).

                      – KabCode
                      Jan 28 at 10:28











                    • @KabCode why would you set the value often? Each thread should minimize access to shared memory. When writing several times you should write only the last value, unless other threads are supposed to see the intermediate values, but then you have no choice other than locking for each write

                      – user463035818
                      Jan 28 at 11:09













                    • @KabCode ah I think now I got what you wanted to say. You are worried by the overhead of creating a new lock instead of reusing the object (?). In that case I suggest you to take a look at the implementation, the lock isnt really doing much, it merely locks the mutex and realeases it, there is not much overhead

                      – user463035818
                      Jan 28 at 11:11
















                    1












                    1








                    1







                    Yes, it makes sense.



                    There are no other advantages, and there are no side-effects (it is a good way to write it).



                    An even better way, is to extract it into a private member function (if you have an operation that is synchronized this way, you might as well give the operation its own name):



                    {
                    // all used variables beside the lock_guard are created and initialized somewhere else
                    ...// do something

                    set_var(new_value);

                    ... // do some other stuff (that might take longer)
                    }

                    void your_class::set_value(int new_value)
                    {
                    std::lock_guard<std::mutex> lock(mut);
                    shared_var = new_value;
                    }





                    share|improve this answer













                    Yes, it makes sense.



                    There are no other advantages, and there are no side-effects (it is a good way to write it).



                    An even better way, is to extract it into a private member function (if you have an operation that is synchronized this way, you might as well give the operation its own name):



                    {
                    // all used variables beside the lock_guard are created and initialized somewhere else
                    ...// do something

                    set_var(new_value);

                    ... // do some other stuff (that might take longer)
                    }

                    void your_class::set_value(int new_value)
                    {
                    std::lock_guard<std::mutex> lock(mut);
                    shared_var = new_value;
                    }






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Jan 28 at 10:19









                    utnapistimutnapistim

                    22.2k23572




                    22.2k23572













                    • Good addition. This will help to keep the code clean. Caveat might be if you have to set this variable often then the costs of creating new locks might be more expensive than lock/unlock (but this is not the scope of the question anymore).

                      – KabCode
                      Jan 28 at 10:28











                    • @KabCode why would you set the value often? Each thread should minimize access to shared memory. When writing several times you should write only the last value, unless other threads are supposed to see the intermediate values, but then you have no choice other than locking for each write

                      – user463035818
                      Jan 28 at 11:09













                    • @KabCode ah I think now I got what you wanted to say. You are worried by the overhead of creating a new lock instead of reusing the object (?). In that case I suggest you to take a look at the implementation, the lock isnt really doing much, it merely locks the mutex and realeases it, there is not much overhead

                      – user463035818
                      Jan 28 at 11:11





















                    • Good addition. This will help to keep the code clean. Caveat might be if you have to set this variable often then the costs of creating new locks might be more expensive than lock/unlock (but this is not the scope of the question anymore).

                      – KabCode
                      Jan 28 at 10:28











                    • @KabCode why would you set the value often? Each thread should minimize access to shared memory. When writing several times you should write only the last value, unless other threads are supposed to see the intermediate values, but then you have no choice other than locking for each write

                      – user463035818
                      Jan 28 at 11:09













                    • @KabCode ah I think now I got what you wanted to say. You are worried by the overhead of creating a new lock instead of reusing the object (?). In that case I suggest you to take a look at the implementation, the lock isnt really doing much, it merely locks the mutex and realeases it, there is not much overhead

                      – user463035818
                      Jan 28 at 11:11



















                    Good addition. This will help to keep the code clean. Caveat might be if you have to set this variable often then the costs of creating new locks might be more expensive than lock/unlock (but this is not the scope of the question anymore).

                    – KabCode
                    Jan 28 at 10:28





                    Good addition. This will help to keep the code clean. Caveat might be if you have to set this variable often then the costs of creating new locks might be more expensive than lock/unlock (but this is not the scope of the question anymore).

                    – KabCode
                    Jan 28 at 10:28













                    @KabCode why would you set the value often? Each thread should minimize access to shared memory. When writing several times you should write only the last value, unless other threads are supposed to see the intermediate values, but then you have no choice other than locking for each write

                    – user463035818
                    Jan 28 at 11:09







                    @KabCode why would you set the value often? Each thread should minimize access to shared memory. When writing several times you should write only the last value, unless other threads are supposed to see the intermediate values, but then you have no choice other than locking for each write

                    – user463035818
                    Jan 28 at 11:09















                    @KabCode ah I think now I got what you wanted to say. You are worried by the overhead of creating a new lock instead of reusing the object (?). In that case I suggest you to take a look at the implementation, the lock isnt really doing much, it merely locks the mutex and realeases it, there is not much overhead

                    – user463035818
                    Jan 28 at 11:11







                    @KabCode ah I think now I got what you wanted to say. You are worried by the overhead of creating a new lock instead of reusing the object (?). In that case I suggest you to take a look at the implementation, the lock isnt really doing much, it merely locks the mutex and realeases it, there is not much overhead

                    – user463035818
                    Jan 28 at 11:11













                    1














                    Using an extra scope specifically to limit the lifetime of an std::lock_guard object is indeed good practice. As the other answers point out, locking your mutex for the shortest period of time will reduce the chances that another thread will block on the mutex.



                    I see one more point that was not mentioned in the other answers: transactional operations. Let's use the classical example of a money transfer between two bank accounts. For your banking program to be correct, the modification of the two bank account's balance must be done without unlocking the mutex in between. Otherwise, it would be possible for another thread to lock the mutex while the program is in a weird state where only one of the accounts was credited/debited while the other account's balance was untouched!



                    With this in mind, it is not enough to ensure that the mutex is locked when each shared resource is modified. Sometimes, you must keep the mutex locked for a period of time spanning the modification of all the shared resources that form a transaction.



                    EDIT:



                    If for some reason keeping the mutex locked for the whole duration of the transaction is not acceptable, you can use the following algorithm:

                    1. Lock mutex, read input data, unlock mutex.

                    2. Perform all needed computations, save results locally.

                    3. Lock mutex, check that input data has not changed, perform the transaction with readily available results, unlock the mutex.



                    If the input data has changed during the execution of step 2, throw away the results and start over with the fresh input data.






                    share|improve this answer


























                    • Good point - could you provide a (pseudo)code sample how you would solve this issue programmatically?

                      – KabCode
                      Jan 29 at 8:29
















                    1














                    Using an extra scope specifically to limit the lifetime of an std::lock_guard object is indeed good practice. As the other answers point out, locking your mutex for the shortest period of time will reduce the chances that another thread will block on the mutex.



                    I see one more point that was not mentioned in the other answers: transactional operations. Let's use the classical example of a money transfer between two bank accounts. For your banking program to be correct, the modification of the two bank account's balance must be done without unlocking the mutex in between. Otherwise, it would be possible for another thread to lock the mutex while the program is in a weird state where only one of the accounts was credited/debited while the other account's balance was untouched!



                    With this in mind, it is not enough to ensure that the mutex is locked when each shared resource is modified. Sometimes, you must keep the mutex locked for a period of time spanning the modification of all the shared resources that form a transaction.



                    EDIT:



                    If for some reason keeping the mutex locked for the whole duration of the transaction is not acceptable, you can use the following algorithm:

                    1. Lock mutex, read input data, unlock mutex.

                    2. Perform all needed computations, save results locally.

                    3. Lock mutex, check that input data has not changed, perform the transaction with readily available results, unlock the mutex.



                    If the input data has changed during the execution of step 2, throw away the results and start over with the fresh input data.






                    share|improve this answer


























                    • Good point - could you provide a (pseudo)code sample how you would solve this issue programmatically?

                      – KabCode
                      Jan 29 at 8:29














                    1












                    1








                    1







                    Using an extra scope specifically to limit the lifetime of an std::lock_guard object is indeed good practice. As the other answers point out, locking your mutex for the shortest period of time will reduce the chances that another thread will block on the mutex.



                    I see one more point that was not mentioned in the other answers: transactional operations. Let's use the classical example of a money transfer between two bank accounts. For your banking program to be correct, the modification of the two bank account's balance must be done without unlocking the mutex in between. Otherwise, it would be possible for another thread to lock the mutex while the program is in a weird state where only one of the accounts was credited/debited while the other account's balance was untouched!



                    With this in mind, it is not enough to ensure that the mutex is locked when each shared resource is modified. Sometimes, you must keep the mutex locked for a period of time spanning the modification of all the shared resources that form a transaction.



                    EDIT:



                    If for some reason keeping the mutex locked for the whole duration of the transaction is not acceptable, you can use the following algorithm:

                    1. Lock mutex, read input data, unlock mutex.

                    2. Perform all needed computations, save results locally.

                    3. Lock mutex, check that input data has not changed, perform the transaction with readily available results, unlock the mutex.



                    If the input data has changed during the execution of step 2, throw away the results and start over with the fresh input data.






                    share|improve this answer















                    Using an extra scope specifically to limit the lifetime of an std::lock_guard object is indeed good practice. As the other answers point out, locking your mutex for the shortest period of time will reduce the chances that another thread will block on the mutex.



                    I see one more point that was not mentioned in the other answers: transactional operations. Let's use the classical example of a money transfer between two bank accounts. For your banking program to be correct, the modification of the two bank account's balance must be done without unlocking the mutex in between. Otherwise, it would be possible for another thread to lock the mutex while the program is in a weird state where only one of the accounts was credited/debited while the other account's balance was untouched!



                    With this in mind, it is not enough to ensure that the mutex is locked when each shared resource is modified. Sometimes, you must keep the mutex locked for a period of time spanning the modification of all the shared resources that form a transaction.



                    EDIT:



                    If for some reason keeping the mutex locked for the whole duration of the transaction is not acceptable, you can use the following algorithm:

                    1. Lock mutex, read input data, unlock mutex.

                    2. Perform all needed computations, save results locally.

                    3. Lock mutex, check that input data has not changed, perform the transaction with readily available results, unlock the mutex.



                    If the input data has changed during the execution of step 2, throw away the results and start over with the fresh input data.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Mar 11 at 21:42

























                    answered Jan 29 at 8:13









                    L.-C. CaronL.-C. Caron

                    1273




                    1273













                    • Good point - could you provide a (pseudo)code sample how you would solve this issue programmatically?

                      – KabCode
                      Jan 29 at 8:29



















                    • Good point - could you provide a (pseudo)code sample how you would solve this issue programmatically?

                      – KabCode
                      Jan 29 at 8:29

















                    Good point - could you provide a (pseudo)code sample how you would solve this issue programmatically?

                    – KabCode
                    Jan 29 at 8:29





                    Good point - could you provide a (pseudo)code sample how you would solve this issue programmatically?

                    – KabCode
                    Jan 29 at 8:29











                    -1














                    I don't see the reason to do it.
                    If you do something so simple as "set one variable" - use atomic<> and you don't need mutex and lock at all. If you do something complicated - extract this code into new function and use lock in its first line.






                    share|improve this answer
























                    • But it is not always worth it to extract into a new function, right?

                      – L. F.
                      Jan 29 at 11:16
















                    -1














                    I don't see the reason to do it.
                    If you do something so simple as "set one variable" - use atomic<> and you don't need mutex and lock at all. If you do something complicated - extract this code into new function and use lock in its first line.






                    share|improve this answer
























                    • But it is not always worth it to extract into a new function, right?

                      – L. F.
                      Jan 29 at 11:16














                    -1












                    -1








                    -1







                    I don't see the reason to do it.
                    If you do something so simple as "set one variable" - use atomic<> and you don't need mutex and lock at all. If you do something complicated - extract this code into new function and use lock in its first line.






                    share|improve this answer













                    I don't see the reason to do it.
                    If you do something so simple as "set one variable" - use atomic<> and you don't need mutex and lock at all. If you do something complicated - extract this code into new function and use lock in its first line.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Jan 29 at 8:39









                    EzhEzh

                    2651418




                    2651418













                    • But it is not always worth it to extract into a new function, right?

                      – L. F.
                      Jan 29 at 11:16



















                    • But it is not always worth it to extract into a new function, right?

                      – L. F.
                      Jan 29 at 11:16

















                    But it is not always worth it to extract into a new function, right?

                    – L. F.
                    Jan 29 at 11:16





                    But it is not always worth it to extract into a new function, right?

                    – L. F.
                    Jan 29 at 11:16


















                    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%2f54399719%2fincluding-stdlock-guard-in-extra-scope%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

                    MongoDB - Not Authorized To Execute Command

                    How to fix TextFormField cause rebuild widget in Flutter

                    in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith