It is the key and difficulty to build high-performance service to improve the system's concurrent throughput. Usually review code when you see synchronized I will think about it, this place can be optimized. Using synchronized enables concurrent threads to become sequential executions, which have a significant impact on system concurrency throughput, my blog http://maoyidao.iteye.com/blog/1149015 introduces a method that can theoretically estimate the system's concurrent processing capability.
So for business scenarios that must use synchronized, here are a few tips to help reduce the lock granularity and improve system concurrency.
Beginner Tips-Optimistic lock
Optimistic lock is suitable for such a scene: Reading does not conflict, writing will conflict. The frequency of reading is much larger than that of writing.
Take the following code as an example, the implementation of the pessimistic lock:
Java code public object get (object key) {synchronized (map) {if (Map.get (key) = null) {//Set Some values} return Map.get (key); } }
public object get (object key) {
synchronized (map) {
if (map.get (key) = null) {
//Set some values
}
r Eturn Map.get (key);
}
Implementation of optimistic Locks:
Java code public object get (object key) { Object val = null; if ((Val = map.get (key) == null) { // lock judgment when map value is null synchronized (map) { if (Val = map.get (key) == null) { // set some value to map ... }    &NBSP} } return map.get (key); }
public object get (object key) {
object val = null;
if (val = map.get (key) = null) {
///Lock
synchronized (map) {
if (val = map.get (key) = null) {
//set some value to map ...}}
return Map.get (key);
}
Intermediate Skills-string.intern ()
Optimistic locks are not a good solution to a large number of write conflicts, but if in many scenarios the lock is not actually directed at a user or an order. For example, a user must create a session before the subsequent operation. However, for network reasons, the request to create a user session and subsequent requests are almost simultaneous, while parallel threads may process subsequent requests first. In general, you need to lock the user sessionmap, such as the optimistic lock above. In this scenario, the use of String.inter () is a more efficient approach. Class string maintains a string pool. When the Intern method is invoked, the string in the pool is returned if the pool already contains a string that is equal to this string object, which is determined by the Equals (object) method. Visible, when the String is the same, String.intern () always returns the same object, so the same user is added to the lock. Because the size of the lock is limited to the specific user, the system obtains the maximum degree of concurrency.
Java code public void dosomething (String uid) {synchronized (Uid.intern ()) {//...} }
public void dosomething (String uid) {
synchronized (Uid.intern ()) {
//...
}
}}
Advanced Skills-Class Concurrenthashmap
The flaw of String.inter () is that the class string maintains that a string pool is placed in the JVM Perm area, and if the number of users is particularly large, the string that is placed into the pool of strings is not controllable, which can lead to oom errors or excessive full GC. How to control the number of locks, while reducing the size of the lock. Java Concurrenthashmap provides a good way to learn from the need to lock the object into multiple bucket, each bucket plus a lock, pseudocode is 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 } }