"Good article recommended" Concurrency Performance optimization: reduced lock granularity

Source: Internet
Author: User

Performance is very important in high-load multithreaded applications. To achieve better performance, developers must be aware of the importance of concurrency. When we need to use concurrency, there is often a resource that must

shared by two or more threads.

In this case, there is a race condition where one of the threads can get the lock (the lock is bound to a specific resource) and the other threads that want to get the lock are blocked. The reality of this synchronization mechanism

Now comes at a price, and to provide you with a good synchronization model, both the JVM and the operating system consume resources. There are three most important factors that enable concurrent implementations to consume significant resources, which are:

    1. Context Switches
    2. Memory synchronization
    3. Blocking

In order to write optimized code for synchronization, you must recognize these three factors and how to reduce them. There are a lot of things you need to pay attention to when writing such code. In this article, I'll introduce you to a

Reduce these factors by reducing the locking granularity of the technology.

Let's start with a basic principle: don't hold unnecessary locks for long periods of time.

Do everything you need to do before you get the lock, just use the lock on the resource that needs to be synchronized, and release it immediately after you run out of it. Let's look at a simple example:


public class Hellosync {    private Map dictionary = new HashMap ();    Public synchronized void Borringdeveloper (string key, String value) {        Long startTime = (new Java.util.Date ()). GetTime ();        Value = value + "_" +starttime;        Dictionary.put (key, value);        System.out.println ("I did this" +     ((new Java.util.Date ()). GetTime ()-StartTime) + "Miliseconds");}    }

In this case, we violated the basic principle because we created two date objects, called SYSTEM.OUT.PRINTLN (), and did a lot of string join operations, but the only one that needed to be synchronized

The operation is "Dictionary.put (key, value);". Let's change the code and turn the synchronization method into a synchronous block that contains only this sentence, and get the following more optimized code:

public class Hellosync {    private Map dictionary = new HashMap ();    public void Borringdeveloper (string key, String value) {        Long startTime = (new Java.util.Date ()). GetTime ();        Value = value + "_" +starttime;        Synchronized (dictionary) {            dictionary.put (key, value);        }        System.out.println ("I did this" + ((new Java.util.Date ()). GetTime ()-StartTime) + "Miliseconds");}    }


the code above can be further optimized, but only to convey this idea. If you are interested in further optimization, please refer to Java.util.concurrent.ConcurrentHashMap.

So how do we lower the lock granularity? Simply put, the lock is done with as few requests as possible. The basic idea is to use separate locks to protect multiple independent state variables in the same class.

Instead of using only one lock for the entire class domain. Let's look at the following simple examples that I've seen in many applications:


public class Grocery {    private final ArrayList fruits = new ArrayList ();    Private final ArrayList vegetables = new ArrayList ();    Public synchronized void addfruit (int index, String fruit) {        fruits.add (index, fruit);    }    Public synchronized void removefruit (int index) {        fruits.remove (index);    }    Public synchronized void addvegetable (int index, String vegetable) {        vegetables.add (index, vegetable);    }    Public synchronized void removevegetable (int index) {        vegetables.remove (index);}    }

The Grocer can add/remove vegetables and fruits from his grocery store. The above implementation of the grocery store, through the basic grocery lock to protect the fruits and vegetables, because the synchronization is

Completed in the method domain. In fact, instead of using this wide range of locks, we can use a separate lock for each resource (fruits and vegetables). Take a look at the improved code:

public class Grocery {    private final ArrayList fruits = new ArrayList ();    Private final ArrayList vegetables = new ArrayList ();    public void addfruit (int index, String fruit) {        synchronized (fruits) fruits.add (index, fruit);    }    public void removefruit (int index) {        synchronized (fruits) {fruits.remove (index);}    }    public void addvegetable (int index, String vegetable) {        synchronized (vegetables) vegetables.add (index, vegetable) ;    }    public void removevegetable (int index) {        synchronized (vegetables) vegetables.remove (index);}    }

After using two locks (separating the locks), we find that there is less lock blocking than with a whole lock. When we use this technique for locks that have a moderate lock,

Optimization is more noticeable. If you apply this method to a lock that is slightly locked, the improvement is relatively small, but it still works. But if you use it in a lock with heavy locks, you will

It is necessary to recognize that the results are not always better.

Please use this technique selectively. If you suspect a lock is a heavy scramble lock, use the following method to confirm whether the above technique is used:

    • Confirm how much your product will compete, multiply this scramble by three times times or five times times (or even 10 times times if you want to be prepared for the foolproof)
    • Make the right tests based on this scramble.
    • Compare the test results of the two scenarios and choose the most appropriate
There are many techniques for improving synchronization performance, but there is only one basic principle for all technologies: don't hold unnecessary locks for long periods of time.

This basic principle can be understood as "as few request locks as possible" as I explained to you earlier, and there are other explanations (implementation methods) that I'll cover later in the article.

The two most important recommendations:

    • Learn about the classes (and their sub-packages) in the Java.util.concurrent package because there are many smart and useful implementations
    • Most concurrent code can be simplified by using a good design pattern. Remember the Enterprise integration patterns heart, they can let you do not have to stay up late.

Note: This article is my own on-line to see the article is good, should be shared to more friends, so reproduced.

Source: Buy Rong original source:Adrianos dadis

"Good article recommended" Concurrency Performance optimization: reduced lock granularity

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.