Including std::lock_guard in extra scope












8















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





























    8















    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



























      8












      8








      8








      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 42 mins ago









      Angew

      132k11251342




      132k11251342










      asked 50 mins ago









      KabCodeKabCode

      868




      868
























          3 Answers
          3






          active

          oldest

          votes


















          5














          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































            2














            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.
              35 mins ago






            • 1





              You could use immediately invoked lambda

              – P i
              32 mins ago











            • Did not downvote. But maybe your answer is something you should consider with every scope. It is not a answer to this particular question? But from my side its still a valued addition.

              – KabCode
              31 mins ago











            • @KabCode Sorry I am a bit too stupid to understand. What do you mean by "something you should consider with every scope"?

              – L. F.
              30 mins ago











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

              – P i
              30 mins ago



















            0














            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
              35 mins ago











            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

























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            5














            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




























              5














              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


























                5












                5








                5







                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 46 mins ago









                AngewAngew

                132k11251342




                132k11251342

























                    2














                    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.
                      35 mins ago






                    • 1





                      You could use immediately invoked lambda

                      – P i
                      32 mins ago











                    • Did not downvote. But maybe your answer is something you should consider with every scope. It is not a answer to this particular question? But from my side its still a valued addition.

                      – KabCode
                      31 mins ago











                    • @KabCode Sorry I am a bit too stupid to understand. What do you mean by "something you should consider with every scope"?

                      – L. F.
                      30 mins ago











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

                      – P i
                      30 mins ago
















                    2














                    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.
                      35 mins ago






                    • 1





                      You could use immediately invoked lambda

                      – P i
                      32 mins ago











                    • Did not downvote. But maybe your answer is something you should consider with every scope. It is not a answer to this particular question? But from my side its still a valued addition.

                      – KabCode
                      31 mins ago











                    • @KabCode Sorry I am a bit too stupid to understand. What do you mean by "something you should consider with every scope"?

                      – L. F.
                      30 mins ago











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

                      – P i
                      30 mins ago














                    2












                    2








                    2







                    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 12 mins ago

























                    answered 36 mins ago









                    L. F.L. F.

                    5248




                    5248








                    • 1





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

                      – L. F.
                      35 mins ago






                    • 1





                      You could use immediately invoked lambda

                      – P i
                      32 mins ago











                    • Did not downvote. But maybe your answer is something you should consider with every scope. It is not a answer to this particular question? But from my side its still a valued addition.

                      – KabCode
                      31 mins ago











                    • @KabCode Sorry I am a bit too stupid to understand. What do you mean by "something you should consider with every scope"?

                      – L. F.
                      30 mins ago











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

                      – P i
                      30 mins ago














                    • 1





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

                      – L. F.
                      35 mins ago






                    • 1





                      You could use immediately invoked lambda

                      – P i
                      32 mins ago











                    • Did not downvote. But maybe your answer is something you should consider with every scope. It is not a answer to this particular question? But from my side its still a valued addition.

                      – KabCode
                      31 mins ago











                    • @KabCode Sorry I am a bit too stupid to understand. What do you mean by "something you should consider with every scope"?

                      – L. F.
                      30 mins ago











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

                      – P i
                      30 mins ago








                    1




                    1





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

                    – L. F.
                    35 mins ago





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

                    – L. F.
                    35 mins ago




                    1




                    1





                    You could use immediately invoked lambda

                    – P i
                    32 mins ago





                    You could use immediately invoked lambda

                    – P i
                    32 mins ago













                    Did not downvote. But maybe your answer is something you should consider with every scope. It is not a answer to this particular question? But from my side its still a valued addition.

                    – KabCode
                    31 mins ago





                    Did not downvote. But maybe your answer is something you should consider with every scope. It is not a answer to this particular question? But from my side its still a valued addition.

                    – KabCode
                    31 mins ago













                    @KabCode Sorry I am a bit too stupid to understand. What do you mean by "something you should consider with every scope"?

                    – L. F.
                    30 mins ago





                    @KabCode Sorry I am a bit too stupid to understand. What do you mean by "something you should consider with every scope"?

                    – L. F.
                    30 mins ago













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

                    – P i
                    30 mins ago





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

                    – P i
                    30 mins ago











                    0














                    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
                      35 mins ago
















                    0














                    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
                      35 mins ago














                    0












                    0








                    0







                    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 44 mins ago









                    utnapistimutnapistim

                    22k23572




                    22k23572













                    • 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
                      35 mins ago



















                    • 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
                      35 mins ago

















                    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
                    35 mins ago





                    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
                    35 mins ago


















                    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

                    What are all the squawk codes?

                    What are differences between VBoxVGA, VMSVGA and VBoxSVGA in VirtualBox?

                    Hudsonelva