Java synchronization-thread lock and condition object

Source: Internet
Author: User

Thread Lock and Condition object

In most multithreaded applications, two and more threads need to share access to the same data, so it is possible to have two threads accessing the same resource at the same time, which is called a race condition .

In Java, in order to solve concurrent data access problems, the concept of locking is generally used to solve.

There are several mechanisms to prevent code from receiving concurrent access interference:

1.synchronized keywords (automatic creation of a lock and related conditions)

Lock interface in the 2.ReentrantLock Class +java.util.concurrent package (introduced in Java5.0)

Use of Reentrantlock
 public void Method() {        boolean flag = false;//标识条件        ReentrantLock locker = new ReentrantLock();        locker.lock();//开启线程锁        try {            //do some work...        } catch (Exception ex) {        } finally {            locker.unlock();//解锁线程        }    }

locker.lock();
Make sure that only one thread enters the critical section, and once a thread enters, it gets the lock object and other threads cannot pass the lock statement. When other threads call lock, they are blocked, knowing that the first thread is releasing the lock object.

locker.unlock();
Unlock operation, be sure to put in finally, because if there is a problem in the Try statement, the lock must be released, otherwise the other threads will always be blocked

Because the system will randomly assign resources to threads, so after the thread obtains the lock object, may be deprived of the operation by the system, this time the other threads access, but found that there is a lock, not to go, can only wait for the thread to get the lock object after the code is executed, release the lock, the second thread to run.

Assuming that the function of a bank transfer, the thread lock operation should be defined in the Bank class transfer method , because so that each bank object has a lock object, two threads access to a bank object, then the lock in a serial way to provide services. However, if each thread accesses a different bank object, each thread gets a different lock object and does not conflict with each other, so it does not cause unnecessary thread blocking.

The lock is reentrant, and the thread can repeat the lock that is already held, and the lock keeps track of the nested use of the lock method through a holding count .

Suppose that after a thread obtains a lock, to execute a method, but a method inside calls the B method, when the thread obtains two lock object, when the thread executes the B method, it will also be locked to prevent other threads from entering, when the B method executes, the lock object becomes one, when the A method is executed , the lock object becomes 0, and the thread releases the lock.

Synchronized keywords

Before we talked about the use of Reentrantlock lock object, but in the system we do not have to use the Reentrantlock lock, Java also provides an internal implicit lock , the keyword is synchronized.

As an example:

public synchronized void Method() {    //do some work...}

Just precede the return value with the synchronized lock, the same effect will be achieved with the Reentrantlock lock above.

Conditional Condition Object

Typically, after the thread has taken the lock object, it discovers that a condition needs to be met to continue execution.

Take the bank procedure to give an example, we need to transfer the account to have sufficient funds to transfer out to the target account, this time need to use the Reentrantlock object, because if we have completed the transfer account has enough funds to determine the thread was interrupted by other threads, and other threads after the execution, The money of the transfer party does not have enough funds, this time because the system has already completed the judgment, so will continue to execute downward, then the banking system will have the problem.

Example:

public void Transfer(int from, int to, double amount) {    if (Accounts[from] > amount)//系统在结束判断之后被剥夺运行权,然后账户通过网银转出所有钱,银行凉凉        DoTransfer(from, to, amount);}

At this point we need to use the Reentrantlock object, we modify the code:

public void Transfer(int from, int to, double amount) {    ReentrantLock locker = new ReentrantLock();    locker.lock();    try {        while (Accounts[from] < amount) {            //等待有足够的钱        }        DoTransfer(from, to, amount);    } catch (Exception ex) {        ex.printStackTrace();    } finally {        locker.unlock();    }}

But then there is a problem, the current thread acquires the lock object, start executing code, found that the money is not enough, into the waiting state, and then the other thread because of the reason that the lock can not be transferred to the account, will continue to enter the waiting state.

How to solve this problem?

Conditional objects Come on!

public void Transfer(int from, int to, double amount) {    ReentrantLock locker = new ReentrantLock();    Condition sufficientFunds = locker.newCondition();//条件对象,    lock.lock();    try {        while (Accounts[from] < amount) {            sufficientFunds.await();            //等待有足够的钱        }        DoTransfer(from, to, amount);        sufficientFunds.signalAll();    } catch (Exception ex) {        ex.printStackTrace();    } finally {        locker.unlock();    }}

The keyword for a conditional object is:Condition, a lock object can have one or more related conditional objects. You can obtain a conditional object by using the lock object. Newcondition method.

In general, the naming of conditional objects needs to be able to reflect the names of the conditions it expresses, so here we call him sufficientfund, which means that the balance is sufficient .

Before entering the lock, we create a condition and then, if the amount is insufficient, call the await method of the conditional object here, notifying the system that the current thread has entered a pending state for other threads to execute. This time your call will be locked, and then the system can call the method again to transfer funds to other accounts, when each transfer is completed, the thread executing the transfer operation at the bottom of the call Signalall notify all the threads can continue to run, because we may be to transfer enough money to the current account, At this point it is possible that the thread will continue to execute (not necessarily you, is to notify all threads, if the notified thread is still not eligible, will continue to call the await method, and complete the transfer operation, and then notify the other suspended threads.

Why don't you just tell the current thread? No, you can call the signal method to notify only one thread, but if the thread operation of the account is still no money (not to transfer to the account), then the thread went into wait, this time no thread can notify other threads, program deadlock, So it's safer to use signal.

The above is the use of reentrantlock+Condition object, then you say I use the synchronized implicit lock what to do?

It is also possible, and does not require

public void Transfer(int from, int to, double amount) {     while (Accounts[from] < amount) {            wait();//这个wait方法是定义在Object类里面的,可以直接用,和条件对象的await一样,挂起线程            //等待有足够的钱        }        DoTransfer(from, to, amount);        notifyAll();//通知其他挂起的线程}

The object class defines the wait, Notifyall, notify methods, corresponding to await, signalall, and signal methods for manipulating implicit locks, andsynchronized can only have one condition. A lock that Reentrantlock explicitly declares can be used to bind multiple condition conditions.

Synchronization block

In addition to the two ways we've talked about acquiring the thread lock, there's another mechanism for getting locks, which is special, called synchronous blocks :

Object locker = new Object();synchronized (locker) {    //do some work}//也可以直接锁当前类的对象sychronized(this){    //do some work}

The above code obtains the lock of object type Locker objects, which is a special lock, in the above code, the object class is created simply to use the lock it holds.

This mechanism is called the synchronization block , the application is also very wide: Sometimes, we do not have to synchronize the whole method, but the method of some of the code block need to synchronize, in this case, if we declare this method as synchronized, Especially when the method is very big, it will cause a lot of waste of resources. So in this case we can use the synchronized keyword to declare the synchronization block:

public void Method() {    //do some work without synchronized    synchronized (this) {        //do some synchronized operation    }}
The concept of a monitor

Locks and conditions are a very important tool in synchronization, but they are not object-oriented. Over the years, researchers in Java have struggled to find a way to ensure the security of multithreading without having to consider how to lock it. One of the most successful solutions is the Monitor, which is built into each of the object variables, which is equivalent to a license. Get the license to operate, do not get the need to block wait.

The monitor has the following characteristics:

1. A monitor is a class that contains only private domains

2. Each monitor object has a related lock

3. Use the lock on the monitor object to lock all methods (for example: if obj is called . method, thelock of the Obj object is automatically obtained at the time of the method call , and the lock is automatically freed when the method ends or returns . because all domains are private, this ensures that no other thread can access the domain inside when the class object is manipulated by a single thread .

4. The lock object can have any number of related conditions

You can also create a monitor class yourself, as long as you meet the above requirements.

In fact, we use the synchronized keyword is to use the monitor to achieve locking unlock , so it is called the internal lock . because the object class implements a monitor, objects are placed inside any object. This is why we can use synchronized (locker) to lock a block of code, in fact, only use the locker object in the built-in monitor. the Monitor class for each object is unique, so it is the only license that can be executed by the thread that gets the license, and the monitor that releases the object after execution is available to other threads.

As an example:

synchronized (this) {    //do some synchronized operation}

It will be compiled in a bytecode file as:

monitorenter;//get monitor,enter the synchronized block            //do some synchronized operationmonitorexit;//leavel the synchronized block,release the monitor

Java synchronization-thread lock and condition object

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.