Necessity of the locks while working with concurrent hash mapPure-Ruby concurrent HashC# Locking, Properties & PermissionsA Bridge Pattern exampleJava Concurrency: CAS vs LockingJava concurrency in practice - Listing 14.9 explanation?How does lock work exactly?Type mismatch in key from map: expected .. Text, received … LongWritableLock for JavaMEOverriding private methods in (non-)static classesHow Runnable is created from Java8 lambda
Xdebug not working over Drush
How can I communicate my issues with a potential date's pushy behavior?
Do I have to cite common CS algorithms?
How to prevent criminal gangs from making/buying guns?
What would it take to get a message to another star?
Why command hierarchy, if the chain of command is standing next to each other?
Why does the cable resistance jump from a low value to high value at a particular frequency?
Do you "gain" 1st level?
Co-workers with a lot of money and openly talk about it
Why is the result of ('b'+'a'+ + 'a' + 'a').toLowerCase() 'banana'?
Are employers legally allowed to pay employees in goods and services equal to or greater than the minimum wage?
Why did IBM make the PC BIOS source code public?
When did Bilbo and Frodo learn that Gandalf was a Maia?
Would the USA be eligible to join the European Union?
"Mouth-breathing" as slang for stupidity
What should we do with manuals from the 80s?
How far did Gandalf and the Balrog drop from the bridge in Moria?
How to not forget things?
What unique challenges/limitations will I face if I start a career as a pilot at 45 years old?
Why is there a dummy union member in some implemetations of std::optional?
Installing Windows to flash UEFI/ BIOS, then reinstalling Ubuntu
Global BGP Routing only by only importing supernet prefixes
How would armour (and combat) change if the fighter didn't need to actually wear it?
Transition to "Starvation Mode" in Survival Situations
Necessity of the locks while working with concurrent hash map
Pure-Ruby concurrent HashC# Locking, Properties & PermissionsA Bridge Pattern exampleJava Concurrency: CAS vs LockingJava concurrency in practice - Listing 14.9 explanation?How does lock work exactly?Type mismatch in key from map: expected .. Text, received … LongWritableLock for JavaMEOverriding private methods in (non-)static classesHow Runnable is created from Java8 lambda
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
Here is the code in one of my classes:
class SomeClass
private Map<Integer, Integer> map = new ConcurrentHashMap<>();
private volatile int counter = 0;
final AtomicInteger sum = new AtomicInteger(0); // will be used in other classes/threads too
private ReentrantLock l = new ReentrantLock();
public void put(String some)
l.lock();
try
int tmp = Integer.parseInt(some);
map.put(counter++, tmp);
sum.getAndAdd(tmp);
finally
l.unlock();
public Double get()
l.lock();
try
//... perform some map resizing operation ...
// some calculations including sum field ...
finally
l.unlock();
You can assume that this class will be used in concurrent environment.
The question is: how do you think is there a necessity of the locks? How does this code smell? :)
java concurrency locking
add a comment |
Here is the code in one of my classes:
class SomeClass
private Map<Integer, Integer> map = new ConcurrentHashMap<>();
private volatile int counter = 0;
final AtomicInteger sum = new AtomicInteger(0); // will be used in other classes/threads too
private ReentrantLock l = new ReentrantLock();
public void put(String some)
l.lock();
try
int tmp = Integer.parseInt(some);
map.put(counter++, tmp);
sum.getAndAdd(tmp);
finally
l.unlock();
public Double get()
l.lock();
try
//... perform some map resizing operation ...
// some calculations including sum field ...
finally
l.unlock();
You can assume that this class will be used in concurrent environment.
The question is: how do you think is there a necessity of the locks? How does this code smell? :)
java concurrency locking
Since you're updating multiple things in the put (the map, the counter, the sum), you need to ensure exclusive access to ensure they are updated consistently. Additionally, thecounter++
isn't atomic.
– Andy Turner
Mar 27 at 11:04
@AndyTurner yeah, but I'm performing increment with already acquired monitor, right?
– Developer87
Mar 27 at 11:17
Yes. And I'm saying that's necessary.
– Andy Turner
Mar 27 at 11:18
Regarding your last question, it smells horrible.new ConcurrentHashMap()
is using a raw type,new AtomicInteger(0L)
does not even compile, the comment “will be used in other classes” contradicts theprivate
modifier, and generally, the purpose is of this code is not clear, but it looks like not doing whatever you intended. As said by Andy Turner, querying a monotonically increasing counter as map key will never find a mapping.
– Holger
Mar 27 at 13:01
add a comment |
Here is the code in one of my classes:
class SomeClass
private Map<Integer, Integer> map = new ConcurrentHashMap<>();
private volatile int counter = 0;
final AtomicInteger sum = new AtomicInteger(0); // will be used in other classes/threads too
private ReentrantLock l = new ReentrantLock();
public void put(String some)
l.lock();
try
int tmp = Integer.parseInt(some);
map.put(counter++, tmp);
sum.getAndAdd(tmp);
finally
l.unlock();
public Double get()
l.lock();
try
//... perform some map resizing operation ...
// some calculations including sum field ...
finally
l.unlock();
You can assume that this class will be used in concurrent environment.
The question is: how do you think is there a necessity of the locks? How does this code smell? :)
java concurrency locking
Here is the code in one of my classes:
class SomeClass
private Map<Integer, Integer> map = new ConcurrentHashMap<>();
private volatile int counter = 0;
final AtomicInteger sum = new AtomicInteger(0); // will be used in other classes/threads too
private ReentrantLock l = new ReentrantLock();
public void put(String some)
l.lock();
try
int tmp = Integer.parseInt(some);
map.put(counter++, tmp);
sum.getAndAdd(tmp);
finally
l.unlock();
public Double get()
l.lock();
try
//... perform some map resizing operation ...
// some calculations including sum field ...
finally
l.unlock();
You can assume that this class will be used in concurrent environment.
The question is: how do you think is there a necessity of the locks? How does this code smell? :)
java concurrency locking
java concurrency locking
edited Mar 27 at 13:45
Developer87
asked Mar 27 at 10:58
Developer87Developer87
5611 gold badge10 silver badges30 bronze badges
5611 gold badge10 silver badges30 bronze badges
Since you're updating multiple things in the put (the map, the counter, the sum), you need to ensure exclusive access to ensure they are updated consistently. Additionally, thecounter++
isn't atomic.
– Andy Turner
Mar 27 at 11:04
@AndyTurner yeah, but I'm performing increment with already acquired monitor, right?
– Developer87
Mar 27 at 11:17
Yes. And I'm saying that's necessary.
– Andy Turner
Mar 27 at 11:18
Regarding your last question, it smells horrible.new ConcurrentHashMap()
is using a raw type,new AtomicInteger(0L)
does not even compile, the comment “will be used in other classes” contradicts theprivate
modifier, and generally, the purpose is of this code is not clear, but it looks like not doing whatever you intended. As said by Andy Turner, querying a monotonically increasing counter as map key will never find a mapping.
– Holger
Mar 27 at 13:01
add a comment |
Since you're updating multiple things in the put (the map, the counter, the sum), you need to ensure exclusive access to ensure they are updated consistently. Additionally, thecounter++
isn't atomic.
– Andy Turner
Mar 27 at 11:04
@AndyTurner yeah, but I'm performing increment with already acquired monitor, right?
– Developer87
Mar 27 at 11:17
Yes. And I'm saying that's necessary.
– Andy Turner
Mar 27 at 11:18
Regarding your last question, it smells horrible.new ConcurrentHashMap()
is using a raw type,new AtomicInteger(0L)
does not even compile, the comment “will be used in other classes” contradicts theprivate
modifier, and generally, the purpose is of this code is not clear, but it looks like not doing whatever you intended. As said by Andy Turner, querying a monotonically increasing counter as map key will never find a mapping.
– Holger
Mar 27 at 13:01
Since you're updating multiple things in the put (the map, the counter, the sum), you need to ensure exclusive access to ensure they are updated consistently. Additionally, the
counter++
isn't atomic.– Andy Turner
Mar 27 at 11:04
Since you're updating multiple things in the put (the map, the counter, the sum), you need to ensure exclusive access to ensure they are updated consistently. Additionally, the
counter++
isn't atomic.– Andy Turner
Mar 27 at 11:04
@AndyTurner yeah, but I'm performing increment with already acquired monitor, right?
– Developer87
Mar 27 at 11:17
@AndyTurner yeah, but I'm performing increment with already acquired monitor, right?
– Developer87
Mar 27 at 11:17
Yes. And I'm saying that's necessary.
– Andy Turner
Mar 27 at 11:18
Yes. And I'm saying that's necessary.
– Andy Turner
Mar 27 at 11:18
Regarding your last question, it smells horrible.
new ConcurrentHashMap()
is using a raw type, new AtomicInteger(0L)
does not even compile, the comment “will be used in other classes” contradicts the private
modifier, and generally, the purpose is of this code is not clear, but it looks like not doing whatever you intended. As said by Andy Turner, querying a monotonically increasing counter as map key will never find a mapping.– Holger
Mar 27 at 13:01
Regarding your last question, it smells horrible.
new ConcurrentHashMap()
is using a raw type, new AtomicInteger(0L)
does not even compile, the comment “will be used in other classes” contradicts the private
modifier, and generally, the purpose is of this code is not clear, but it looks like not doing whatever you intended. As said by Andy Turner, querying a monotonically increasing counter as map key will never find a mapping.– Holger
Mar 27 at 13:01
add a comment |
2 Answers
2
active
oldest
votes
Let's look at the operations inside public void put(String some)
.
map.put(counter++, tmp);
sum.getAndAdd(tmp);
Now let's look at the individual parts.
counter
is a volatile variable. So it only provides memory visibility but not atomicity. Sincecounter++
is a compound operation, you need a lock to achieve atomicity.map.put(key, value)
is atomic since it is aConcurrentHashMap
.sum.getAndAdd(tmp)
is atomic since it is aAtomicInteger
.
As you can see, except counter++
every other operation is atomic. However, you are trying to achieve some function by combining all these operations. To achieve atomicity at the functionality level, you need a lock. This will help you to avoid surprising side effects when the threads interleave between the individual atomic operations.
So you need a lock because counter++
is not atomic and you want to combine a few atomic operations to achieve some functionality (assuming you want this to be atomic).
thanks a lot! What if I convert volatile counter to atomic integer, will it still make sense to have external locks? I guess yes, because as you mentioned, we need to maintain functional consistency overall.
– Developer87
Mar 27 at 13:48
Yes. Even If you make thecounter
atomic, to maintain functional consistency you need locks.
– samzz
Mar 27 at 14:00
add a comment |
Since you always increment counter
when you use it as a key to put into this map:
map.put(counter++, tmp);
when you come to read it again:
return sum / map.get(counter);
map.get(counter)
will be null
, so this results in a NPE (unless you put more than 2^32 things into the map, ofc). (I'm assuming you mean sum.get()
, otherwise it won't compile).
As such, you can have equivalent functionality without any locks:
class SomeClass
public void put(String some) /* do nothing */
public Double get()
throw new NullPointerException();
You've not really fixed the problem with your edit. divisor
will still be null, so the equivalent functionality without locks would be:
class SomeClass
private final AtomicInteger sum = new AtomicInteger(0);
public void put(String some)
sum.getAndAdd(Integer.parseInt(some));
public Double get()
return sum.get();
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%2f55375557%2fnecessity-of-the-locks-while-working-with-concurrent-hash-map%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Let's look at the operations inside public void put(String some)
.
map.put(counter++, tmp);
sum.getAndAdd(tmp);
Now let's look at the individual parts.
counter
is a volatile variable. So it only provides memory visibility but not atomicity. Sincecounter++
is a compound operation, you need a lock to achieve atomicity.map.put(key, value)
is atomic since it is aConcurrentHashMap
.sum.getAndAdd(tmp)
is atomic since it is aAtomicInteger
.
As you can see, except counter++
every other operation is atomic. However, you are trying to achieve some function by combining all these operations. To achieve atomicity at the functionality level, you need a lock. This will help you to avoid surprising side effects when the threads interleave between the individual atomic operations.
So you need a lock because counter++
is not atomic and you want to combine a few atomic operations to achieve some functionality (assuming you want this to be atomic).
thanks a lot! What if I convert volatile counter to atomic integer, will it still make sense to have external locks? I guess yes, because as you mentioned, we need to maintain functional consistency overall.
– Developer87
Mar 27 at 13:48
Yes. Even If you make thecounter
atomic, to maintain functional consistency you need locks.
– samzz
Mar 27 at 14:00
add a comment |
Let's look at the operations inside public void put(String some)
.
map.put(counter++, tmp);
sum.getAndAdd(tmp);
Now let's look at the individual parts.
counter
is a volatile variable. So it only provides memory visibility but not atomicity. Sincecounter++
is a compound operation, you need a lock to achieve atomicity.map.put(key, value)
is atomic since it is aConcurrentHashMap
.sum.getAndAdd(tmp)
is atomic since it is aAtomicInteger
.
As you can see, except counter++
every other operation is atomic. However, you are trying to achieve some function by combining all these operations. To achieve atomicity at the functionality level, you need a lock. This will help you to avoid surprising side effects when the threads interleave between the individual atomic operations.
So you need a lock because counter++
is not atomic and you want to combine a few atomic operations to achieve some functionality (assuming you want this to be atomic).
thanks a lot! What if I convert volatile counter to atomic integer, will it still make sense to have external locks? I guess yes, because as you mentioned, we need to maintain functional consistency overall.
– Developer87
Mar 27 at 13:48
Yes. Even If you make thecounter
atomic, to maintain functional consistency you need locks.
– samzz
Mar 27 at 14:00
add a comment |
Let's look at the operations inside public void put(String some)
.
map.put(counter++, tmp);
sum.getAndAdd(tmp);
Now let's look at the individual parts.
counter
is a volatile variable. So it only provides memory visibility but not atomicity. Sincecounter++
is a compound operation, you need a lock to achieve atomicity.map.put(key, value)
is atomic since it is aConcurrentHashMap
.sum.getAndAdd(tmp)
is atomic since it is aAtomicInteger
.
As you can see, except counter++
every other operation is atomic. However, you are trying to achieve some function by combining all these operations. To achieve atomicity at the functionality level, you need a lock. This will help you to avoid surprising side effects when the threads interleave between the individual atomic operations.
So you need a lock because counter++
is not atomic and you want to combine a few atomic operations to achieve some functionality (assuming you want this to be atomic).
Let's look at the operations inside public void put(String some)
.
map.put(counter++, tmp);
sum.getAndAdd(tmp);
Now let's look at the individual parts.
counter
is a volatile variable. So it only provides memory visibility but not atomicity. Sincecounter++
is a compound operation, you need a lock to achieve atomicity.map.put(key, value)
is atomic since it is aConcurrentHashMap
.sum.getAndAdd(tmp)
is atomic since it is aAtomicInteger
.
As you can see, except counter++
every other operation is atomic. However, you are trying to achieve some function by combining all these operations. To achieve atomicity at the functionality level, you need a lock. This will help you to avoid surprising side effects when the threads interleave between the individual atomic operations.
So you need a lock because counter++
is not atomic and you want to combine a few atomic operations to achieve some functionality (assuming you want this to be atomic).
answered Mar 27 at 11:52
samzzsamzz
1291 silver badge3 bronze badges
1291 silver badge3 bronze badges
thanks a lot! What if I convert volatile counter to atomic integer, will it still make sense to have external locks? I guess yes, because as you mentioned, we need to maintain functional consistency overall.
– Developer87
Mar 27 at 13:48
Yes. Even If you make thecounter
atomic, to maintain functional consistency you need locks.
– samzz
Mar 27 at 14:00
add a comment |
thanks a lot! What if I convert volatile counter to atomic integer, will it still make sense to have external locks? I guess yes, because as you mentioned, we need to maintain functional consistency overall.
– Developer87
Mar 27 at 13:48
Yes. Even If you make thecounter
atomic, to maintain functional consistency you need locks.
– samzz
Mar 27 at 14:00
thanks a lot! What if I convert volatile counter to atomic integer, will it still make sense to have external locks? I guess yes, because as you mentioned, we need to maintain functional consistency overall.
– Developer87
Mar 27 at 13:48
thanks a lot! What if I convert volatile counter to atomic integer, will it still make sense to have external locks? I guess yes, because as you mentioned, we need to maintain functional consistency overall.
– Developer87
Mar 27 at 13:48
Yes. Even If you make the
counter
atomic, to maintain functional consistency you need locks.– samzz
Mar 27 at 14:00
Yes. Even If you make the
counter
atomic, to maintain functional consistency you need locks.– samzz
Mar 27 at 14:00
add a comment |
Since you always increment counter
when you use it as a key to put into this map:
map.put(counter++, tmp);
when you come to read it again:
return sum / map.get(counter);
map.get(counter)
will be null
, so this results in a NPE (unless you put more than 2^32 things into the map, ofc). (I'm assuming you mean sum.get()
, otherwise it won't compile).
As such, you can have equivalent functionality without any locks:
class SomeClass
public void put(String some) /* do nothing */
public Double get()
throw new NullPointerException();
You've not really fixed the problem with your edit. divisor
will still be null, so the equivalent functionality without locks would be:
class SomeClass
private final AtomicInteger sum = new AtomicInteger(0);
public void put(String some)
sum.getAndAdd(Integer.parseInt(some));
public Double get()
return sum.get();
add a comment |
Since you always increment counter
when you use it as a key to put into this map:
map.put(counter++, tmp);
when you come to read it again:
return sum / map.get(counter);
map.get(counter)
will be null
, so this results in a NPE (unless you put more than 2^32 things into the map, ofc). (I'm assuming you mean sum.get()
, otherwise it won't compile).
As such, you can have equivalent functionality without any locks:
class SomeClass
public void put(String some) /* do nothing */
public Double get()
throw new NullPointerException();
You've not really fixed the problem with your edit. divisor
will still be null, so the equivalent functionality without locks would be:
class SomeClass
private final AtomicInteger sum = new AtomicInteger(0);
public void put(String some)
sum.getAndAdd(Integer.parseInt(some));
public Double get()
return sum.get();
add a comment |
Since you always increment counter
when you use it as a key to put into this map:
map.put(counter++, tmp);
when you come to read it again:
return sum / map.get(counter);
map.get(counter)
will be null
, so this results in a NPE (unless you put more than 2^32 things into the map, ofc). (I'm assuming you mean sum.get()
, otherwise it won't compile).
As such, you can have equivalent functionality without any locks:
class SomeClass
public void put(String some) /* do nothing */
public Double get()
throw new NullPointerException();
You've not really fixed the problem with your edit. divisor
will still be null, so the equivalent functionality without locks would be:
class SomeClass
private final AtomicInteger sum = new AtomicInteger(0);
public void put(String some)
sum.getAndAdd(Integer.parseInt(some));
public Double get()
return sum.get();
Since you always increment counter
when you use it as a key to put into this map:
map.put(counter++, tmp);
when you come to read it again:
return sum / map.get(counter);
map.get(counter)
will be null
, so this results in a NPE (unless you put more than 2^32 things into the map, ofc). (I'm assuming you mean sum.get()
, otherwise it won't compile).
As such, you can have equivalent functionality without any locks:
class SomeClass
public void put(String some) /* do nothing */
public Double get()
throw new NullPointerException();
You've not really fixed the problem with your edit. divisor
will still be null, so the equivalent functionality without locks would be:
class SomeClass
private final AtomicInteger sum = new AtomicInteger(0);
public void put(String some)
sum.getAndAdd(Integer.parseInt(some));
public Double get()
return sum.get();
edited Mar 27 at 12:00
answered Mar 27 at 11:23
Andy TurnerAndy Turner
92.8k10 gold badges101 silver badges164 bronze badges
92.8k10 gold badges101 silver badges164 bronze badges
add a comment |
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%2f55375557%2fnecessity-of-the-locks-while-working-with-concurrent-hash-map%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
Since you're updating multiple things in the put (the map, the counter, the sum), you need to ensure exclusive access to ensure they are updated consistently. Additionally, the
counter++
isn't atomic.– Andy Turner
Mar 27 at 11:04
@AndyTurner yeah, but I'm performing increment with already acquired monitor, right?
– Developer87
Mar 27 at 11:17
Yes. And I'm saying that's necessary.
– Andy Turner
Mar 27 at 11:18
Regarding your last question, it smells horrible.
new ConcurrentHashMap()
is using a raw type,new AtomicInteger(0L)
does not even compile, the comment “will be used in other classes” contradicts theprivate
modifier, and generally, the purpose is of this code is not clear, but it looks like not doing whatever you intended. As said by Andy Turner, querying a monotonically increasing counter as map key will never find a mapping.– Holger
Mar 27 at 13:01