Beginner Tips-Optimistic lock
Optimistic locking is suitable for scenarios where reading does not conflict and writing conflicts. The frequency of reading is much larger than writing.
In the following code, for example, the implementation of pessimistic locks:
Java code
public object get (object key) {
synchronized (map) {
if (map.get (key) = = null) {
//Set some values
}
return Map.get (key);
}
}
Implementation of optimistic locking:
Java code
public object get (object key) {
Object val = null;
if (val = map.get (key) = = null) {
//When map value is NULL then lock judgment
synchronized (map) {
if (val = map.get (key) = = null) {
//Set some value to map ...
}
}
}
return Map.get (key);
}
Intermediate Tips-String.intern ()
Optimistic locking is not a good solution to a large number of write conflicts, but if many scenarios, the lock is actually for a user or an order. For example, a user must first create a session in order to perform subsequent operations. However, due to network reasons, the request to create a user session and subsequent requests are almost at the same time, while a parallel thread may handle subsequent requests first. In general, you need to lock the user sessionmap, such as the above optimistic lock. In this scenario, the lock can be limited to the user itself, that is, from the original
Lock.lock ();
int Num=storage.get (key);
Storage.set (key,num+1);
Lock.unlock ();
Change to:
Lock.lock (key);
int Num=storage.get (key);
Storage.set (key,num+1);
Lock.unlock (key);
This comparison is similar to the concept of database table locks and row locks, and apparently the concurrency of row locks is much higher than table locks.
Using String.inter () is a concrete implementation of this idea. Class string maintains a string pool. When the Intern method is called, if the pool already contains a string equal to this string object (which is determined by the Equals (object) method), the string in the pool is returned. It can be seen that when the String is the same, String.intern () always returns the same object, thereby enabling the same user to be locked. Because the granularity of the lock is limited to the specific user, the system obtains the maximum concurrency.
Java code
Public void DoSomething (String uid) {
synchronized (Uid.intern ()) {
// ...
}
}
Copyonwritemap?
Now that the "concept of row locks in a database is similar", we have to mention that the Copyonwrite class in Mvcc,java implements the MVCC. Copy on write is such a mechanism. When we read the shared data, we read it directly and do not need synchronization. When we modify the data, we copy the current data copy, then modify it on the copy, and then replace the original data with the modified copy. This method is called copy on Write.
However,, the JDK does not provide copyonwritemap, why? Here is a good answer, that is already has the concurrenthashmap, why still need Copyonwritemap?
Fredrik Bromee wrote
I Guess this depends the your use case, and why would you need a copyonwritemap when you already has a concurrenthashmap?
For a plain lookup table with many readers and only one or few updates it is a good fit.
Compared to a copy on write collection:
Read Concurrency:
Equal to a copy on write collection. Several readers can retrieve elements from the map concurrently in a lock-free fashion.
Write Concurrency:
Better concurrency than the copy on write collections This basically serialize updates (one update at a time). Using A concurrent hash map you have a good chance of doing several updates concurrently. If your hash keys is evenly distributed.
If you don't want to having the effect of a copy on write map, you can always initialize a concurrenthashmap with a concurrency Level of 1.
Advanced Tips-Class Concurrenthashmap
The flaw of String.inter () is that the class string maintains a string pool that is placed in the JVM Perm area, and if the number of users is particularly large, a string that is placed in the strings pool is not controllable, potentially causing an oom error or an excessive full GC. How to control the number of locks, while reducing the size of the lock? Use Java Concurrenthashmap directly? Or do you want to join your own finer control? So you can learn from the Concurrenthashmap way, will need to lock the object into multiple buckets, each bucket plus a lock, pseudo-code as follows:
Java code
Map locks = new map ();
List Lockkeys = new list ();
for (int number: 1- 10000) {
Object Lockkey = new Object ();
Lockkeys.add (Lockkey);
Locks.put (Lockkey, new Object ());
}
Public void DoSomething (String uid) {
Object Lockkey = Lockkeys.get (Uid.hash ()% lockkeys.size ());
Object lock = Locks.get (Lockkey);
synchronized (lock) {
//Do something
}
}
For more free tutorials Please join Dubbo Technical Exchange: 548209960
Java high concurrency High availability architecture: 632103578
3 implementations of Java High concurrency lock