Java multithreading-Lock detailed and sample code _java

Source: Internet
Author: User
Tags throw exception

Starting with Java 5, the Java.util.concurrent.locks package contains some of the lock implementations, so you don't have to implement your own locks. But you still need to know how to use these locks.

A simple lock.

Let's start with a synchronized block in Java:

public class counter{
  private int count = 0;

  public Int Inc. () {
    synchronized (this) {return
      ++count
    }
}}

You can see that there is a synchronized (this) code block in the Inc () method. The code block guarantees that only one thread at a time can perform a return ++count. Although the code in the synchronized synchronization block can be more complex, the simple operation of ++count is enough to express the meaning of thread synchronization.

The following Counter classes use Lock instead of synchronized to achieve the same goal:

public class counter{
  private lock lock = new Lock ();
  private int count = 0;

  public Int Inc () {
    lock.lock ();
    int newcount = ++count;
    Lock.unlock ();
    Return Newcount
  }
}

The lock () method locks the lock instance object so that all threads that invoke the lock () method on the object are blocked until the unlock () method of the lock object is invoked.

Here is a simple implementation of the Lock class:

public class counter{public
class lock{
  private Boolean islocked = false;

  Public synchronized void Lock ()
    throws interruptedexception{while
    (islocked) {wait
      ();
    }
    IsLocked = true;
  }

  public synchronized void Unlock () {
    islocked = false;
    Notify ();
  }


Note the while (islocked) loop, which is called the spin lock. When IsLocked is true, the thread that calls lock () blocks waiting on the wait () call. To prevent the thread from receiving the Notify () call and returning (also known as false wakeup) from wait (). This thread will re-examine the islocked condition to determine whether it is safe to continue execution or to wait again, rather than thinking that the thread is awakened and can proceed safely. If IsLocked is false, the current thread exits the while (islocked) loop and sets islocked back to true so that other threads that are calling the lock () method can lock the lock instance.

When the thread completes the code in the critical section (between lock () and Unlock ()), the Unlock () is invoked. Executing unlock () will reset the islocked to False and notify (wake) one (if any) of the wait () function in the lock () method and the thread that is in the waiting state.

The reentrant nature of Locks

The synchronized synchronization block in Java is reentrant. This means that if a Java thread enters the synchronized synchronization block in the code and thus obtains a lock on the corresponding thread of the synchronization object used by the synchronization block, the thread can enter another Java block of code that is synchronized with the same pipe object. Here is an example:

public class reentrant{public
  synchronized outer () {
    inner ();
  }

  Public synchronized inner () {
    //do something
  }
}

Note that both outer () and inner () are declared as synchronized, which is equivalent in the Java and synchronized (this) block. If a thread invokes outer (), there is nothing wrong with calling inner () in outer (), because both methods (code blocks) are synchronized by the same pipe object ("this"). If a thread already has a lock on a pipe object, it has access to all the blocks of code that are synchronized with the process object. This is what can be reentrant. A thread can enter a block of code synchronized with any lock it already has.

The lock implementation given above is not reentrant. If we rewrite the Reentrant class as follows, when the thread calls outer (), it blocks at the Lock.lock () of the inner () method.

public class reentrant2{
  lock lock = new Lock ();

  public outer () {
    lock.lock ();
    Inner ();
    Lock.unlock ();
  }

  Public synchronized inner () {
    lock.lock ();
    Do something
    lock.unlock ();
  }


The thread that calls outer () first locks the lock instance, and then continues to invoke inner (). In the inner () method, the thread will attempt to lock the lock instance again, resulting in the action failing (that is, the thread is blocked) because the lock instance is already locked in the outer () method.

Two times lock () does not call unlock (), the second call lock will block, after watching the lock () implementation, you will find the reason is obvious:

public class lock{
  Boolean islocked = false;

  Public synchronized void Lock ()
    throws interruptedexception{while
    (islocked) {wait
      ();
    }
    IsLocked = true;
  }

  ...
}

Whether a thread is allowed to exit the lock () method is determined by the condition in the while loop (Spin lock). The current judgment condition is that the lock operation is allowed only if islocked is false, without regard to which thread has locked it.

In order for this Lock class to be reentrant, we need to make a small change to it:

public class lock{
  Boolean islocked = false;
  Thread lockedby = null;
  int lockedcount = 0;

  Public synchronized void Lock ()
    throws interruptedexception{
    Thread callingthread =
      Thread.CurrentThread ();
    while (islocked && lockedby!= callingthread) {wait
      ();
    }
    IsLocked = true;
    lockedcount++;
    Lockedby = Callingthread;
 }

  public synchronized void Unlock () {
    if (thread.curentthread () = =
      This.lockedby) {
      lockedcount--;

      if (Lockedcount = = 0) {
        islocked = false;
        Notify ();

  }} ...
}

Note that the current while loop (Spin lock) also takes into account the threads that have locked the lock instance. If the current lock object is not lock (islocked = False), or if the current calling thread has added a lock to the lock instance, the while loop is not executed, and the thread that calls the lock () can exit the method (translator: "Allowed to exit the method"). In the current semantics, it means that no wait () is invoked to cause blocking.

In addition, we need to record the number of times the same thread repeatedly locks a lock object. Otherwise, a unblock () call unlocks the entire lock, even if the current lock has been locked more than once. We do not want the lock to be lifted until the unlock () call does not reach the number of lock () calls.

Now this Lock class can be reentrant.

The fairness of the lock

Java synchronized blocks do not guarantee the order of the threads attempting to enter them. Therefore, if multiple threads are constantly competing to access the same synchronized synchronization block, there is a risk that one or more threads will never get access-that is, access is always assigned to other threads. This situation is called thread starvation. In order to avoid this problem, the lock needs to achieve fairness. The locks shown in this article are internally implemented with synchronized synchronization blocks, so they do not guarantee fairness.

Call Unlock () in the Finally statement

If Lock is used to protect the critical section, and the critical section is likely to throw an exception, it is important to call unlock () in the finally statement. This will ensure that the lock object can be unlocked so that other threads can continue to lock it. Here's an example:

Lock.lock ();
try{
  //do critical section Code,
  //which may throw exception
} finally {
  lock.unlock ();
}

This simple structure guarantees that the lock object can be unlocked when the critical section throws an exception. If the unlock () is not called in the finally statement, when the critical section throws an exception, the lock object stays in the locked state forever, which causes all other threads that invoke lock () on the lock object to block.

The above is about the Java multi-wire lock data collation, follow-up continue to supplement the relevant information, thank you for your support of this site!

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.