ConcurrentHashMap atomic operation to remove all entries except one
up vote
2
down vote
favorite
Given a ConcurrentHashMap<String, String>
contains following entries:
this.map = new ConcurrentHashMap<>();
this.map.put("user", "user description");
this.map.put("session", "session description");
this.map.put("test", "test description");
The map is accessed by multiple threads.
How to remove all keys, except session
in an atomic way?
Will this code work as I expect, without race conditions? Is forEach
method atomic? Is there any other way to achieve this atomically?
map.forEach((key, value) -> {
if (!key.equals("session")) {
map.remove(key);
}
});
java concurrency atomic concurrenthashmap
|
show 1 more comment
up vote
2
down vote
favorite
Given a ConcurrentHashMap<String, String>
contains following entries:
this.map = new ConcurrentHashMap<>();
this.map.put("user", "user description");
this.map.put("session", "session description");
this.map.put("test", "test description");
The map is accessed by multiple threads.
How to remove all keys, except session
in an atomic way?
Will this code work as I expect, without race conditions? Is forEach
method atomic? Is there any other way to achieve this atomically?
map.forEach((key, value) -> {
if (!key.equals("session")) {
map.remove(key);
}
});
java concurrency atomic concurrenthashmap
I'm guessing.equals("session)
is a typo? And that your actual code does have a closing"
?
– Mark
Nov 10 at 15:57
@Mark, yest it's typo, and my actual code has enclosing ".
– Mariusz.v7
Nov 10 at 16:00
Can the value associated with "session" be modified by other threads? And will there always be a "session" key in the map?
– arshajii
Nov 10 at 16:23
@arshajii no, the value associated with "session" never changes, but all other keys can be modified. Yes, session is always present in the map.
– Mariusz.v7
Nov 10 at 16:26
Ok, in that case check out my answer below.
– arshajii
Nov 10 at 16:29
|
show 1 more comment
up vote
2
down vote
favorite
up vote
2
down vote
favorite
Given a ConcurrentHashMap<String, String>
contains following entries:
this.map = new ConcurrentHashMap<>();
this.map.put("user", "user description");
this.map.put("session", "session description");
this.map.put("test", "test description");
The map is accessed by multiple threads.
How to remove all keys, except session
in an atomic way?
Will this code work as I expect, without race conditions? Is forEach
method atomic? Is there any other way to achieve this atomically?
map.forEach((key, value) -> {
if (!key.equals("session")) {
map.remove(key);
}
});
java concurrency atomic concurrenthashmap
Given a ConcurrentHashMap<String, String>
contains following entries:
this.map = new ConcurrentHashMap<>();
this.map.put("user", "user description");
this.map.put("session", "session description");
this.map.put("test", "test description");
The map is accessed by multiple threads.
How to remove all keys, except session
in an atomic way?
Will this code work as I expect, without race conditions? Is forEach
method atomic? Is there any other way to achieve this atomically?
map.forEach((key, value) -> {
if (!key.equals("session")) {
map.remove(key);
}
});
java concurrency atomic concurrenthashmap
java concurrency atomic concurrenthashmap
edited Nov 10 at 16:28
nullpointer
34.4k1070139
34.4k1070139
asked Nov 10 at 15:56
Mariusz.v7
730716
730716
I'm guessing.equals("session)
is a typo? And that your actual code does have a closing"
?
– Mark
Nov 10 at 15:57
@Mark, yest it's typo, and my actual code has enclosing ".
– Mariusz.v7
Nov 10 at 16:00
Can the value associated with "session" be modified by other threads? And will there always be a "session" key in the map?
– arshajii
Nov 10 at 16:23
@arshajii no, the value associated with "session" never changes, but all other keys can be modified. Yes, session is always present in the map.
– Mariusz.v7
Nov 10 at 16:26
Ok, in that case check out my answer below.
– arshajii
Nov 10 at 16:29
|
show 1 more comment
I'm guessing.equals("session)
is a typo? And that your actual code does have a closing"
?
– Mark
Nov 10 at 15:57
@Mark, yest it's typo, and my actual code has enclosing ".
– Mariusz.v7
Nov 10 at 16:00
Can the value associated with "session" be modified by other threads? And will there always be a "session" key in the map?
– arshajii
Nov 10 at 16:23
@arshajii no, the value associated with "session" never changes, but all other keys can be modified. Yes, session is always present in the map.
– Mariusz.v7
Nov 10 at 16:26
Ok, in that case check out my answer below.
– arshajii
Nov 10 at 16:29
I'm guessing
.equals("session)
is a typo? And that your actual code does have a closing "
?– Mark
Nov 10 at 15:57
I'm guessing
.equals("session)
is a typo? And that your actual code does have a closing "
?– Mark
Nov 10 at 15:57
@Mark, yest it's typo, and my actual code has enclosing ".
– Mariusz.v7
Nov 10 at 16:00
@Mark, yest it's typo, and my actual code has enclosing ".
– Mariusz.v7
Nov 10 at 16:00
Can the value associated with "session" be modified by other threads? And will there always be a "session" key in the map?
– arshajii
Nov 10 at 16:23
Can the value associated with "session" be modified by other threads? And will there always be a "session" key in the map?
– arshajii
Nov 10 at 16:23
@arshajii no, the value associated with "session" never changes, but all other keys can be modified. Yes, session is always present in the map.
– Mariusz.v7
Nov 10 at 16:26
@arshajii no, the value associated with "session" never changes, but all other keys can be modified. Yes, session is always present in the map.
– Mariusz.v7
Nov 10 at 16:26
Ok, in that case check out my answer below.
– arshajii
Nov 10 at 16:29
Ok, in that case check out my answer below.
– arshajii
Nov 10 at 16:29
|
show 1 more comment
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
Your forEach()
will not happen atomically, since each remove()
call is synchronized independently.
You could try doing this by creating a new map and replacing the old one with it:
ConcurrentMap<String, String> newMap = new ConcurrentHashMap<>();
newMap.put("session", this.map.get("session"));
this.map = newMap;
Threads viewing this.map
before the switch will have the old view, but the atomic "removal" can be thought of as taking place when you assign the new map. The only other issue is when another thread modifies the value associated with "session"
in the original map between the 2nd and 3rd lines (or if that key isn't even present), but as you said in your comment that never happens.
The solution you proposed is good for me. One more question comes to my mind: what aboutforEach()
method? Is it synchronized or not? If it is, then assuming potentially very long operation inside it, what would happen if two threads will try to execute it? One will wait for another, or both will get a copy/view of the map without blocking?
– Mariusz.v7
Nov 10 at 16:38
No, it's not. Why don't you just test it? Add a Thread.sleep() inside the forEach, and start a thread that uses the map. And you'll know.
– JB Nizet
Nov 10 at 16:41
@JBNizet yes I started to play with it like you just wrote. I just wanted someone more experienced than me to confirm my guesses.
– Mariusz.v7
Nov 10 at 16:43
1
@Mariusz.v7 You can also look at the source to see this.
– arshajii
Nov 10 at 16:45
thanks for the answers!
– Mariusz.v7
Nov 10 at 16:47
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
Your forEach()
will not happen atomically, since each remove()
call is synchronized independently.
You could try doing this by creating a new map and replacing the old one with it:
ConcurrentMap<String, String> newMap = new ConcurrentHashMap<>();
newMap.put("session", this.map.get("session"));
this.map = newMap;
Threads viewing this.map
before the switch will have the old view, but the atomic "removal" can be thought of as taking place when you assign the new map. The only other issue is when another thread modifies the value associated with "session"
in the original map between the 2nd and 3rd lines (or if that key isn't even present), but as you said in your comment that never happens.
The solution you proposed is good for me. One more question comes to my mind: what aboutforEach()
method? Is it synchronized or not? If it is, then assuming potentially very long operation inside it, what would happen if two threads will try to execute it? One will wait for another, or both will get a copy/view of the map without blocking?
– Mariusz.v7
Nov 10 at 16:38
No, it's not. Why don't you just test it? Add a Thread.sleep() inside the forEach, and start a thread that uses the map. And you'll know.
– JB Nizet
Nov 10 at 16:41
@JBNizet yes I started to play with it like you just wrote. I just wanted someone more experienced than me to confirm my guesses.
– Mariusz.v7
Nov 10 at 16:43
1
@Mariusz.v7 You can also look at the source to see this.
– arshajii
Nov 10 at 16:45
thanks for the answers!
– Mariusz.v7
Nov 10 at 16:47
add a comment |
up vote
1
down vote
accepted
Your forEach()
will not happen atomically, since each remove()
call is synchronized independently.
You could try doing this by creating a new map and replacing the old one with it:
ConcurrentMap<String, String> newMap = new ConcurrentHashMap<>();
newMap.put("session", this.map.get("session"));
this.map = newMap;
Threads viewing this.map
before the switch will have the old view, but the atomic "removal" can be thought of as taking place when you assign the new map. The only other issue is when another thread modifies the value associated with "session"
in the original map between the 2nd and 3rd lines (or if that key isn't even present), but as you said in your comment that never happens.
The solution you proposed is good for me. One more question comes to my mind: what aboutforEach()
method? Is it synchronized or not? If it is, then assuming potentially very long operation inside it, what would happen if two threads will try to execute it? One will wait for another, or both will get a copy/view of the map without blocking?
– Mariusz.v7
Nov 10 at 16:38
No, it's not. Why don't you just test it? Add a Thread.sleep() inside the forEach, and start a thread that uses the map. And you'll know.
– JB Nizet
Nov 10 at 16:41
@JBNizet yes I started to play with it like you just wrote. I just wanted someone more experienced than me to confirm my guesses.
– Mariusz.v7
Nov 10 at 16:43
1
@Mariusz.v7 You can also look at the source to see this.
– arshajii
Nov 10 at 16:45
thanks for the answers!
– Mariusz.v7
Nov 10 at 16:47
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
Your forEach()
will not happen atomically, since each remove()
call is synchronized independently.
You could try doing this by creating a new map and replacing the old one with it:
ConcurrentMap<String, String> newMap = new ConcurrentHashMap<>();
newMap.put("session", this.map.get("session"));
this.map = newMap;
Threads viewing this.map
before the switch will have the old view, but the atomic "removal" can be thought of as taking place when you assign the new map. The only other issue is when another thread modifies the value associated with "session"
in the original map between the 2nd and 3rd lines (or if that key isn't even present), but as you said in your comment that never happens.
Your forEach()
will not happen atomically, since each remove()
call is synchronized independently.
You could try doing this by creating a new map and replacing the old one with it:
ConcurrentMap<String, String> newMap = new ConcurrentHashMap<>();
newMap.put("session", this.map.get("session"));
this.map = newMap;
Threads viewing this.map
before the switch will have the old view, but the atomic "removal" can be thought of as taking place when you assign the new map. The only other issue is when another thread modifies the value associated with "session"
in the original map between the 2nd and 3rd lines (or if that key isn't even present), but as you said in your comment that never happens.
answered Nov 10 at 16:27
arshajii
98.8k18177247
98.8k18177247
The solution you proposed is good for me. One more question comes to my mind: what aboutforEach()
method? Is it synchronized or not? If it is, then assuming potentially very long operation inside it, what would happen if two threads will try to execute it? One will wait for another, or both will get a copy/view of the map without blocking?
– Mariusz.v7
Nov 10 at 16:38
No, it's not. Why don't you just test it? Add a Thread.sleep() inside the forEach, and start a thread that uses the map. And you'll know.
– JB Nizet
Nov 10 at 16:41
@JBNizet yes I started to play with it like you just wrote. I just wanted someone more experienced than me to confirm my guesses.
– Mariusz.v7
Nov 10 at 16:43
1
@Mariusz.v7 You can also look at the source to see this.
– arshajii
Nov 10 at 16:45
thanks for the answers!
– Mariusz.v7
Nov 10 at 16:47
add a comment |
The solution you proposed is good for me. One more question comes to my mind: what aboutforEach()
method? Is it synchronized or not? If it is, then assuming potentially very long operation inside it, what would happen if two threads will try to execute it? One will wait for another, or both will get a copy/view of the map without blocking?
– Mariusz.v7
Nov 10 at 16:38
No, it's not. Why don't you just test it? Add a Thread.sleep() inside the forEach, and start a thread that uses the map. And you'll know.
– JB Nizet
Nov 10 at 16:41
@JBNizet yes I started to play with it like you just wrote. I just wanted someone more experienced than me to confirm my guesses.
– Mariusz.v7
Nov 10 at 16:43
1
@Mariusz.v7 You can also look at the source to see this.
– arshajii
Nov 10 at 16:45
thanks for the answers!
– Mariusz.v7
Nov 10 at 16:47
The solution you proposed is good for me. One more question comes to my mind: what about
forEach()
method? Is it synchronized or not? If it is, then assuming potentially very long operation inside it, what would happen if two threads will try to execute it? One will wait for another, or both will get a copy/view of the map without blocking?– Mariusz.v7
Nov 10 at 16:38
The solution you proposed is good for me. One more question comes to my mind: what about
forEach()
method? Is it synchronized or not? If it is, then assuming potentially very long operation inside it, what would happen if two threads will try to execute it? One will wait for another, or both will get a copy/view of the map without blocking?– Mariusz.v7
Nov 10 at 16:38
No, it's not. Why don't you just test it? Add a Thread.sleep() inside the forEach, and start a thread that uses the map. And you'll know.
– JB Nizet
Nov 10 at 16:41
No, it's not. Why don't you just test it? Add a Thread.sleep() inside the forEach, and start a thread that uses the map. And you'll know.
– JB Nizet
Nov 10 at 16:41
@JBNizet yes I started to play with it like you just wrote. I just wanted someone more experienced than me to confirm my guesses.
– Mariusz.v7
Nov 10 at 16:43
@JBNizet yes I started to play with it like you just wrote. I just wanted someone more experienced than me to confirm my guesses.
– Mariusz.v7
Nov 10 at 16:43
1
1
@Mariusz.v7 You can also look at the source to see this.
– arshajii
Nov 10 at 16:45
@Mariusz.v7 You can also look at the source to see this.
– arshajii
Nov 10 at 16:45
thanks for the answers!
– Mariusz.v7
Nov 10 at 16:47
thanks for the answers!
– Mariusz.v7
Nov 10 at 16:47
add a comment |
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%2f53240690%2fconcurrenthashmap-atomic-operation-to-remove-all-entries-except-one%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
I'm guessing
.equals("session)
is a typo? And that your actual code does have a closing"
?– Mark
Nov 10 at 15:57
@Mark, yest it's typo, and my actual code has enclosing ".
– Mariusz.v7
Nov 10 at 16:00
Can the value associated with "session" be modified by other threads? And will there always be a "session" key in the map?
– arshajii
Nov 10 at 16:23
@arshajii no, the value associated with "session" never changes, but all other keys can be modified. Yes, session is always present in the map.
– Mariusz.v7
Nov 10 at 16:26
Ok, in that case check out my answer below.
– arshajii
Nov 10 at 16:29