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);

);









share|improve this question























  • 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














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);

);









share|improve this question























  • 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












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);

);









share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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
















  • 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












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.






share|improve this answer




















  • 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










  • @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










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',
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%2f53240690%2fconcurrenthashmap-atomic-operation-to-remove-all-entries-except-one%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























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.






share|improve this answer




















  • 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










  • @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














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.






share|improve this answer




















  • 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










  • @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












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.






share|improve this answer












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.







share|improve this answer












share|improve this answer



share|improve this answer










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 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










  • @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










  • 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

















 

draft saved


draft discarded















































 


draft saved


draft discarded














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





















































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

Top Tejano songwriter Luis Silva dead of heart attack at 64

政党

天津地下鉄3号線