Problems with the JAVA thread lock __java

Source: Internet
Author: User

In general, thread deadlock is a problem in every language that uses threads, and it is common to encounter thread deadlock in Java development. The author often encounters the deadlock problem in the program development, and is often helpless. This article shares some of the author's views on thread deadlock in Java development.

A. What is a thread
When it comes to thread deadlock, we first have to understand what a Java thread is. A process of a program contains multiple threads, and a thread is a logical flow running in a process. Multithreading allows multiple instruction streams to be executed concurrently in a program, each of which is called a thread, independent of each other.

A thread, also known as a lightweight process, has independent execution control as a process, and the operating system is responsible for scheduling, the difference being that the thread does not have separate storage space, but rather shares a single storage space with other threads in the process, making communication between threads simpler than the process. The author's experience is to write a multi-line program that must be aware of whether each thread interferes with the work of other threads. Each process begins its lifecycle with a single thread called the "main thread", at which point the main thread creates a peer. If the main thread is stagnant, the system switches to its peer thread. A thread associated with a process will now form a peer pool, and a thread can kill any of its peers.

Because each thread can read and write the same shared data. This creates a new problem: Because data sharing can cause synchronization problems, it can lead to deadlocks.

Two. Mechanism of deadlock
Performance improvements brought about by multithreading are at the cost of reliability, mainly because of the possibility of thread deadlocks. Deadlocks are situations where multiple threads are blocked at the same time, and one or all of them are waiting for a resource to be freed. The program does not function properly because the thread is blocked indefinitely. Simply put: When a thread is deadlocked, the first thread waits for the second thread to release the resource, while the second thread waits for the first thread to release the resource. Here is a popular example: If two people on the sidewalk meet head-on, in order to give way to the other side, two people at the same time take a step, both sides can not pass, and at the same time to the other side of the step, so still unable to pass. Assuming this continues, the deadlock will occur.

The root cause of deadlocks is the improper use of "synchronized" keywords to manage threads ' access to specific objects. The role of the "synchronized" keyword is to ensure that only one thread at a time is allowed to execute a particular block of code, so that the thread that is allowed to execute must first have exclusive access to the variable or object. When a thread accesses an object, the thread locks the object, which causes other threads that also want to access the same object to be blocked until the first thread releases the lock it adds to the object.

Each object in Java has a lock corresponding to it. However, Java does not provide separate lock and unlock operations. The following author analyzes the deadlock of the two processes "locked" and "lock Dead".

(1) lock
The synchronization mechanism is required for many threads to consider sharing data or coordinating execution state with other threads in execution. So most applications require threads to communicate with each other to synchronize their actions, and the easiest way to achieve synchronization in a Java program is to lock them. In Java programming, all objects have locks. Threads can use the Synchronized keyword to obtain a lock. At any one time for an instance of a given class, a method or a synchronized block of code can only be executed by one thread. This is because the code requires a lock on the object before it is executed.

To prevent access to shared resources at the same time, threads can lock and unlock the resource before and after using the resource. Locking a shared variable allows Java threads to communicate and synchronize quickly and easily. A line Chengjo a lock on an object to know that no other thread can access the object. Even in a preemptive model, no other thread can access the object until the locked thread wakes up, completes the work, and unlocks the lock. Threads that attempt to access a locked object usually go to sleep until the locked thread unlocks. Once the locks are opened, the sleep processes are awakened and moved to the ready queue.

(2) Lock dead
If there are several concurrent threads in the program that compete for resources, it is important to ensure that the balance is balanced. System equalization means that each thread can fully access the limited resources during execution, and there is no thread of starvation and deadlock in the system. When multiple concurrent threads attempt to occupy two locks at the same time, there is a case of a lock conflict. If one thread occupies a required lock on another thread, it is possible to deadlock when waiting with each other.

When writing multithreaded code, I think deadlock is one of the most difficult problems to deal with. Because deadlocks can occur in the most unexpected places, it is time-consuming and laborious to find and fix them. For example, a common example is the following procedure.

    public int sumarrays (int[] A1, int[] A2) {  
      int value = 0;  
      int size = A1.length;  
      if (size = = a2.length) {  
         synchronized (A1) {//1        
           synchronized (A2) {//2 for          
             (int i=0; i<size; i++)  
                value + = A1[i] + a2[i];}}    
      return value;  
    }   

This code locks the two array objects before accessing the two array objects in the sum operation. It is short in form and suitable for the task to be performed, but unfortunately it has a potential problem. The problem is that it buries the seed of the dead lock.

Three. How to detect the root cause of deadlocks
Java does not provide a mechanism for detecting deadlocks. I think the most effective tool used to analyze Java code problems is still Java thread dump. When a deadlock occurs, the JVM is usually in a suspended state, and thread dump can give static and stable information, and finding deadlocks requires only finding the problematic thread. When a Java Virtual machine deadlock occurs, it is observed from the operating system that the CPU occupancy rate of the virtual machine is zero and will soon disappear from top or prstat output. You can collect thread dumps to find thread for the "Waiting for monitor entry" and if a lot of thread is waiting to lock the same address (because for Java, an object has only one lock), this means that the deadlock is likely to occur.

To determine the problem, the author proposes to collect the thread dump again after a few minutes, if the output is the same, still a lot of thread is waiting to lock the same address, then it must be a deadlock. How to find the thread that currently holds the lock is the key to solving the problem. The general approach is to search thread dump, find "locked, and locate the thread that holds the lock. If the thread holding the lock is still waiting to lock the other object, follow the above method until the root of the deadlock is found.

In addition, this thread is often seen in the thread dump, which is a thread that waits for a condition to voluntarily discard the lock. It is sometimes necessary to analyze such threads, especially the conditions in which the thread waits.

Four. Several common deadlocks and countermeasures
There is no easy way to resolve deadlocks, because threads have different causes for deadlocks and often have a high load. Most software tests do not produce enough load, so it is not possible to expose all thread errors. In this article, the author will discuss the common 4 kinds of typical deadlocks and solutions in the development process.

(1) Database deadlock
In a database, a connection can block another connection if it occupies a database lock required by another connection. If two or more than two connections are blocking each other, they cannot continue to execute, which is called a database deadlock.

The database deadlock problem is not easy to handle, usually when the data row is updated, the data row needs to be locked, the update is performed, and the lock is released when the enclosing transaction is committed or rolled back. Because of the database platform, the isolation level of the configuration, and the query hints, the locks acquired may be fine-grained or coarse-grained, blocking (or not blocking) other queries against the same data row, table, or database. Based on the database schema, read and write operations require traversing or updating multiple indexes, validating constraints, executing triggers, and so on. More locks will be introduced for each requirement. In addition, other applications may be accessing certain objects in the same database schema and getting locks that are available to different applications.

All of these factors are combined, and the database deadlock is almost impossible to eliminate. Thankfully, database deadlocks are usually recoverable: When a database discovers a deadlock, it forces a connection to be destroyed (usually with a minimal connection) and rolls back its transaction. This frees all locks associated with the closed transaction, allowing at least one of the other connections to get a lock that they are blocking.

Because the database has this typical deadlock handling behavior, the database can often only retry the entire transaction when a database deadlock problem occurs. When a database connection is destroyed, an exception that can be caught by the application is thrown and identified as a database deadlock. If a deadlock exception is allowed to propagate beyond the layer of code that initializes the transaction, the code layer can start a new transaction and do all previous work.

If there is a problem, try again, because the database is free to acquire locks, so it is almost impossible to guarantee that two or more two threads do not have a database deadlock. This method can at least guarantee that the application will function correctly when certain database deadlocks occur.

(2) resource pool runs out of deadlock

The increase in the client caused the resource pool to run out of deadlock due to the load, that is, the resource pool is too small, and each thread needs more resources than is available in the pool. Assume that the connection pool has up to 10 connections and 10 concurrent calls to the outside. Each of these threads requires a database connection to empty the pool. Each thread now executes a nested call. All threads cannot continue, but they do not discard their first database connection. In this way, all 10 threads will be deadlocked.

Studying this type of deadlock discovers that there are a large number of threads in the thread store waiting to acquire resources, as well as an equal number of idle and non-blocking active database connections. When the application is deadlocked, if you can detect the connection pool at run time, you can confirm that the connection pool is actually empty.

Methods for fixing such deadlocks include increasing the size of the connection pool or refactoring the code so that a single thread does not need to use many database connections at the same time. Or you can set up internal calls using a different connection pool, and internal calls can continue using your own connection pool, even if the external calling connection pool is empty.

(3) Single-threaded, multiple-conflict database connection deadlock

Nested calls to the same thread sometimes have deadlocks, which usually occur even in a non-high load system. When the first (outer) connection has acquired the database lock required for the second (internal) connection, the second connection permanently blocks the first connection and waits for the first connection to be committed or rolled back, which has a deadlock situation. Because the database does not notice the relationship between two connections, the database does not detect the case as a deadlock. This code will cause a deadlock even if no concurrency exists. There are several specific variants of this scenario that can involve multiple threads and more than two database connections.

(4) Java Virtual Machine lock conflict with database lock

This situation occurs when the database lock coexists with the Java Virtual Machine lock. In this case, a thread occupies a database lock and attempts to acquire a Java Virtual machine lock. At the same time, another thread occupies a Java virtual machine lock and attempts to acquire a database lock. At this point, the database found that one of the connections blocked another connection, but the deadlock was not detected because the connection could not be prevented from continuing. The Java virtual machine discovers that there is one thread in the synchronized lock and there is another thread that is trying to enter, so even if the Java virtual function detects deadlocks and processes them, it does not detect the situation.

All in all, deadlocks in a Java application is a big problem-it can cause the entire application to end slowly, and it's hard to detach and fix, especially if the developer is unfamiliar with how to analyze the deadlock environment.

Five. Rules of thumb for deadlocks
The author summarizes the following deadlock problems in the development of the experience.
(1) For most Java programmers, the simplest way to prevent deadlocks is to introduce serial numbers to competing resources, and if a thread requires several resources, it must first get a small number of resources, and then request a large number of resources. You can increase the use of synchronization keys in Java code to reduce deadlocks, but doing so can also affect performance. If the load is too heavy, deadlocks may also occur inside the database.

(2) To understand the behavior of database lock occurrence. It is assumed that any database access is likely to fall into the database deadlock condition, but all will be retried correctly. For example, learn how to get a complete thread dump from an application server and get a list of database connections from the database (including blocked connections), and know which Java line threads relative each database connection is associated with. The easiest way to understand the mapping between Java threads and database connections is to add logging capabilities to the connection pool access mode.

(3) When making nested calls, understand which calls use the same database connection as other calls. Even if a nested call is running in the same global transaction, it will still use a different database connection without causing a nested deadlock.

(4) Ensure that there is a large enough pool of resources at peak concurrency. (5) Avoid performing database calls or performing other operations unrelated to the Java virtual machine when owning a Java virtual machine lock.
 
Most importantly, multithreaded design is difficult, but designing the system in detail before you start programming can help you avoid the difficulty of discovering deadlocks. Deadlocks cannot be solved at the language level, and a good design is needed to avoid deadlocks.

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.