Deep Learning on Java multi-thread programming lock optimization and java multi-thread programming

Source: Internet
Author: User

Deep Learning on Java multi-thread programming lock optimization and java multi-thread programming

Body

When programming in a concurrent environment, you need to use a lock mechanism to synchronize operations between multiple threads to ensure mutually exclusive access to shared resources. Locking may cause performance damage, which seems to be well known. However, locking itself will not cause much performance consumption. The performance is mainly in the process of obtaining locks from threads. If there is only one thread competing lock, and there is no multi-thread competition at this time, then the JVM will be optimized, then the performance consumption caused by the locking can basically be ignored. Therefore, standardizing locking operations and optimizing the use of locks can avoid unnecessary thread competition, which not only improves program performance, but also avoids the possibility of thread deadlock caused by nonstandard locking, improve program robustness. The following describes several lock optimization ideas.

I. Try not to lock the Method

When locking a common member function, the thread obtains the object lock of the object where the method is located. The entire object is locked. This also means that if the object provides multiple Synchronization Methods for different services, the entire object is locked and a business is being processed, other unrelated business threads must also be wait. The following example shows the situation:

The LockMethod class contains two Synchronization Methods called in two business processes:

public class LockMethod { public synchronized void busiA() {  for (int i = 0; i < 10000; i++) {   System.out.println(Thread.currentThread().getName() + "deal with bussiness A:"+i);  } } public synchronized void busiB() {  for (int i = 0; i < 10000; i++) {   System.out.println(Thread.currentThread().getName() + "deal with bussiness B:"+i);  } }}

BUSSA is A thread class used to process business A. It calls the busiA () method of LockMethod:

public class BUSSB extends Thread { LockMethod lockMethod; void deal(LockMethod lockMethod){  this.lockMethod = lockMethod; } @Override public void run() {  super.run();  lockMethod.busiB(); }}

TestLockMethod class, which uses the thread BUSSA and BUSSB for business processing:

public class TestLockMethod extends Thread { public static void main(String[] args) {  LockMethod lockMethod = new LockMethod();  BUSSA bussa = new BUSSA();  BUSSB bussb = new BUSSB();  bussa.deal(lockMethod);  bussb.deal(lockMethod);  bussa.start();  bussb.start(); }}

Run the program. We can see that bussb cannot enter the busiB () function during the execution of the thread bussa, because the lockMethod object lock is obtained by the thread bussa.

Ii. narrow down the synchronization code block and lock data only

Sometimes for programming convenience, some people will synchnoized a large piece of code. If some operations in this code block are not related to shared resources, they should be placed outside the synchronization block, to avoid lock hold for a long time, other threads remain in the waiting state. In particular, some cyclic operations and synchronous I/O operations. It is not only to narrow down the synchronization block in the range of code lines, but also to narrow down the synchronization block in the execution logic. For example, you should add more conditions for judgment and synchronize the synchronization when the conditions are met, instead of performing conditional judgment after synchronization, we try to reduce unnecessary logic for entering the synchronization block.

3. Try not to include a lock in the lock

This often happens. After the thread obtains the lock, it calls the synchronization method of another object in the synchronization method block and obtains the second lock, this may lead to a request with multiple locks in the call stack, and complicated and difficult to analyze exceptions in the case of multiple threads, resulting in deadlocks. The following code shows this situation:

synchronized(A){ synchronized(B){  } }

Or the synchronous method is called in the synchronization block:

Synchronized (A) {B B = objArrayList. get (0); B. method (); // This is A synchronous method}

The solution is to jump out and apply the lock. do not include the lock:

{  B b = null; synchronized(A){ b = objArrayList.get(0); } b.method();}

4. privatize locks and manage locks internally

The lock is used as a private object. It is safer to obtain this object externally. The object may be directly locked by other threads. At this time, the thread holds the object lock of the object, for example, in the following situation:

Class A {public void method1 () {}} class B {public void method1 () {A a = new A (); synchronized (a) {// lock a directly. method1 ();}}}

In this way, the object lock of object a is held by the outside, which makes it dangerous to use the lock in multiple external places, and also causes troubles in reading the logic flow of the Code. A better way is to manage locks in the internal class. When the external needs a synchronization scheme, the synchronous operation is also provided through the interface:

class A { private Object lock = new Object(); public void method1() {  synchronized (lock){     } }}class B { public void method1() {  A a = new A();  a.method1(); }}

5. Perform proper lock Decomposition

Consider the following procedure:

Public class GameServer {public Map <String, List <Player> tables = new HashMap <String, List <Player> (); public void join (Player player, Table table) {if (player. getAccountBalance ()> table. getLimit () {synchronized (tables) {List <Player> tablePlayers = tables. get (table. getId (); if (tablePlayers. size () <9) {tablePlayers. add (player) ;}}} public void leave (Player player, Table table) {/* omitted */} public void createTable () {/* omitted */} public void destroyTable (Table table) {/* omitted */}}

In this example, the join method only uses one synchronization lock to obtain the List <Player> object in tables, and then checks whether the number of players is smaller than 9. If yes, it adds a Player. When there are thousands of lists <Player> in tables, the competition for tables locks will be very fierce. Here, we can consider breaking down the lock: After the data is quickly retrieved, lock the List <Player> object so that other threads can quickly compete for the tables object lock:

Public class GameServer {
Public Map <String,
List <Player> tables = new HashMap <String,
List <Player> ();
Public void join (Player player, Table table ){
If (player. getAccountBalance ()> table. getLimit ()){
List <Player> tablePlayers = null;
Synchronized (tables ){
TablePlayers = tables. get (table. getId ());
}
Synchronized (tablePlayers ){
If (tablePlayers. size () <9 ){
TablePlayers. add (player );
}
}
}
}
Public void leave (Player player, Table table ){
/* Omitted */
}
Public void createTable (){
/* Omitted */
}
Public void destroyTable (Table table ){
/* Omitted */
}
}

Related Article

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.