Reputation: 585
When i synchronize a block by an instance variable, it's variable can be just accessed (not edited) by other thread?
Example:
If a thread invokes setValue
, the value
gets lock.
But if another thread invokes getValue
during the lock, I don't know if this call goes to wait mode.
setValue(Integer newValue){
synchronized (this.value){
this.value = newValue;
}
}
getValue(){
return this.value;
}
Upvotes: 1
Views: 3309
Reputation: 56
You could use ConcurrentHashMap.
I gona sugest this too.
Complementing with this link, where have a good explanation and other type of Map.
HashMap vs ConcurrentHashMap vs SynchronizedMap
Cheers.
Upvotes: 1
Reputation: 27115
When i synchronize a block by an instance variable...
You can't synchronize on a variable, you can only synchronize on an object. Your code does this:
synchronized (lockObject) {
...
}
That is not synchronizing on the variable named lockObject
; Your code is synchronizing on the new Counter()
instance to which the lockObject
variable refers.
...it's variable can be just accessed...?
The synchronized block does not prevent other threads from modifying the lockObject
variable, and it does not prevent other threads from modifying the Counter
instance. The only thing that the synchronized block prevents is, it prevents other threads from synchronizing on the same object at the same time.
If you want to prevent two threads from using the Counter at the same time, then its up to you to wrap a synchronized(lockObject)
block around every place where your code uses it.
Upvotes: 2
Reputation: 131326
I would like that many threads access my map but synchronous by key... And all threads access any value by key passed
You could use ConcurrentHashMap
.
Reading operations are cheap and not blocking thanks to a lock performed only on related key.
1) You are not compelled to synchronize the map when you do a get()
from the map if you deem that a not updated reading is not a problem.
Which seems to be your use case.
2) If as in your example the value associated to the key in the map must reflect the exact value, you could synchronize the setValue()
method to ensure that concurrent calls are well taken into consideration in the map value.
Be aware, the setValue()
method should be synchronized only if the code executed inside it modifies the map according to the current map state.
Otherwise you don't need to synchronize it.
For example :
public class ExampleClass{
private Map<Character, Integer> map = new ConcurrentHashMap<>();
void synchronized setValue(String key, Integer newValue){
// some processings ...
this.map.put(key, newValue);
}
Integer getValue(String key){
return map.get(key);
}
}
Upvotes: 1
Reputation: 417
When you are synchronizing on some object, it doesn't mean that this object is "locked" - it means that you acquired so called "intrinsic lock" associated with object (each object have one).
When some synchornization block is guarded by some object, it basically means that you will need to acquire intrinsic lock associated with that object in order to enter that block. When you are leaving synchronized block - you will also release lock.
Similar with synchronized methods - in that case "this" reference is used to guard method.
So "value" of object that is used for guarding synchronized block is not locked when some thread is inside synchronized block.
You can test it in easy way with something like this:
public class Test {
Counter lockObject = new Counter();
public static void main(String[] args) {
new Test().go();
}
private void go() {
new Thread(() -> {
synchronized (lockObject) {
while(true) {
System.out.println("Inside thread");
}
}
}).start();
while(true) {
lockObject.inc();
System.out.println(String.format("Accessing lock object: %d", lockObject.get()));
}
}
}
class Counter {
int i = 0;
public void inc() {
i++;
}
public int get() {
return i;
}
}
Here thread is forever inside synchronized block guarded by "lockObject" but stil main thread can interact with it.
Upvotes: 3