Including std::lock_guard in extra scope
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
add a comment |
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
add a comment |
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
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
c++ locking mutex
edited 42 mins ago
Angew
132k11251342
132k11251342
asked 50 mins ago
KabCodeKabCode
868
868
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
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.
add a comment |
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.
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
|
show 8 more comments
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;
}
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
add a comment |
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.
add a comment |
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.
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.
answered 46 mins ago
AngewAngew
132k11251342
132k11251342
add a comment |
add a comment |
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.
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
|
show 8 more comments
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.
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
|
show 8 more comments
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.
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.
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
|
show 8 more comments
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
|
show 8 more comments
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;
}
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
add a comment |
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;
}
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
add a comment |
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;
}
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;
}
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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