Knowledge summarization and instance code _java of Java Lock

Source: Internet
Author: User

What locks are in Java

This problem after I read <java concurrent programming > After all can't answer, explain oneself to the concept of the lock not understand enough. So again looked at the contents of the book, suddenly a bit open the feeling of the forehead. It seems that the best way to learn is to take questions to learn and solve problems.

There are two main types of locks in Java: Internal lock synchronized and display lock Java.util.concurrent.locks.Lock. But the thought of this seemingly summed up is not quite right. Should be a series of locks implemented by the Java built-in lock and concurrent.

Why this says, because everything in Java is an object, and Java has a built-in lock for each object, also known as an object lock/internal lock. The synchronized is used to complete the associated lock operation.

And because the implementation of synchronized some flaws and the complexity of concurrent scenarios, someone developed an explicit lock, which is derived from the Java.util.concurrent.locks.Lock. Of course, it is now built into the JDK1.5 and later versions.

Synchronized

First of all, to see the use of more synchronized, my daily work is mostly used in it. Synchronized is used to provide a lock mechanism for a block of code that implicitly holds a lock in a Java object called a built-in lock (intrinsic) or monitor lock (monitor locks). The thread automatically obtains the lock before entering the block that is protected by the synchronized until the code is complete (or it may be an exception) to automatically release the lock. Built-in locks are mutually exclusive, and a lock can be held by only one thread at a time, which can cause threads to block after the lock is held. This enables the thread safety of the code to ensure atomicity.

Can be reentrant

Now that the Java built-in Lock is mutually exclusive and the thread behind it causes blocking, what happens if the thread holding the lock enters again trying to get the lock? For example, one of the following conditions:

public class BaseClass {public
  synchronized void Do () {
    System.out.println (' is base ');
  }

public class Sonclass extends BaseClass {public
  synchronized void does () {
   System.out.println ("is Son");
   Super.do ();
  }


Sonclass son = new Sonclass ();
Son.do ();

The Do method of the derived class, in addition to holding a lock first, and then entering the lock again when the super.do () is invoked, should be locked if the lock is mutually exclusive.

However, this is not the case, because the internal lock is a reentrant feature, that is, the lock implements a reentrant mechanism, reference count management. When thread 1 holds the object's lock A, the reference to lock A is calculated plus 1. Then, when thread 1 obtains lock a again, thread 1 or lock A will be counted to add 1. Of course, every time you exit the sync block, it will decrease by 1 until the lock is released for 0 o'clock.

Some characteristics of synchronized

How code is decorated

Cosmetic method

public class BaseClass {public
  synchronized void Do () {
    System.out.println (' is base ');
  }



This is to lock a method directly, and you need to get the lock when you enter this method block.

Cosmetic code block

public class BaseClass {
  private static Object lock = new Object ();
  public void Do () {
    synchronized (lock) {
      System.out.println (' is base ');
    }
  }



This will reduce the scope of the lock to a part of the code block in the method, which improves the flexibility of the lock, after all, the lock granularity control is also a key issue of the lock.

Type of Object lock

Often see some code in the use of synchronized more special, look at the following code:

public class BaseClass {
  private static Object lock = new Object ();
  public void does () {
    synchronized (lock) {
    }
  } public
  
  synchronized void Dovoid () {
  }
  
  synchronized static void Dostaticvoid () {
  } public
  
  static void Dostaticvoid () {
    synchronized ( Baseclass.class) {
    
    }
  }  

}

Here are four scenarios: Modifying the code block, modifying the method, modifying the static method, and modifying the BaseClass class object. So what's the difference?

Cosmetic code block

In this case, we create an object lock that uses synchronized (lock) in the code, which means that the lock is used with the built-in locks of this object. In this case, the control of the lock is given to an object. There is, of course, another way of doing this:

public void does () {
  synchronized (this) {
    System.out.println (' is base ');
  }

Using this means the lock of the current object. Here also the key to the built-in lock, I provide a lock to protect the code, no matter which threads are facing the same lock.

Cosmetic Object method

This direct modification in the method is our situation? It is similar to a cosmetic code block, except that this is the default use of this, which is the lock of the current object. Writing code like this is simpler and clearer. As I said before, the difference between the modified code block and the main control granularity is the difference.

modifying static methods

Is there anything different about static methods? is not the same, the lock is not this, and the this object points to the class, that is, the type lock. Because class information in Java is loaded into the method constant area, the global is unique. This actually provides a global lock.

Class object that modifies classes

This situation is actually similar to modifying a static method, but it's still a good way to provide more flexible control granularity.

Summary

Through the analysis and understanding of these situations, we can see that the main core idea of the built-in lock is to provide a lock for a piece of code that can be used for mutual exclusion, and function like a switch.

Java in the built-in lock also provides some implementation, the main feature is that Java are objects, and each object has a lock, so you can choose what kind of lock according to the situation.

Java.util.concurrent.locks.Lock

Synchronized, most of the situation is enough, but now the complexity of the system in concurrent programming is more and more high, so there are always many scenes synchronized processing will be more laborious. Or, as <java concurrent programming > says, lock in concurrent is a complement to the internal lock, providing more advanced features.

Java.util.concurrent.locks.Lock Simple Analysis

This interface abstracts the main operations of the lock, so that the locks derived from lock have these basic features: unconditional, round-robin, timed, interruptible. And the operation of lock and unlock is done explicitly. The following is its code:

Public interface Lock {
  void lock ();
  void Lockinterruptibly () throws interruptedexception;
  Boolean trylock ();
  Boolean Trylock (long time, Timeunit unit) throws interruptedexception;
  void unlock ();
  Condition newcondition ();
}

Reentrantlock

Reentrantlock is the lock that can be reset, even the name is so explicit. Reentrantlock provides similar semantics to synchronized, but Reentrantlock must be explicitly invoked, for example:

public class BaseClass {
  private lock lock = new Reentrantlock ();

  public void Do () {
    lock.lock ();
    try {
    //...
    } finally {
     lock.unlock ();

}}}

This way is still more clear for code reading, but there is a problem, if you forget to add a try finally or forget to write Lock.unlock () caused the lock is not released, it is likely to lead to a number of deadlocks, synchronized is not the risk.

Trylock

Reentrantlock is the implementation of the lock interface, so nature has its characteristics, of which there are trylock. Trylock is trying to acquire a lock, and if the lock is already occupied by another thread, return false immediately, if it is not then it should be occupied and return true, indicating that the lock has been obtained.

Another Trylock method carries parameters, and the purpose of this method is to specify a time in which to attempt to acquire the lock and give up if the time has not been obtained.

Because the Trylock lock is not always blocked waiting, so can more circumvent the occurrence of deadlock.

lockinterruptibly

Lockinterruptibly is a priority response interrupt when a thread acquires a lock, and if an interrupt throw interrupt exception is detected, it is handled by the upper code. In this case, an exit mechanism is provided for a round-robin lock. To better understand the interruptible lock operation, write a demo to understand.

Package com.test;
Import Java.util.Date;

Import Java.util.concurrent.locks.ReentrantLock;
 
 public class Testlockinterruptibly {static Reentrantlock lock = new Reentrantlock (); public static void Main (string[] args} {thread thread1 = new Thread (new Runnable () {@Override public void run ()
   {try {doprint ("Thread 1 Get lock.");
   Do123 ();
   
  Doprint ("Thread 1 end.");
  catch (Interruptedexception e) {doprint ("Thread 1 is interrupted.");

 }
  }
 }); Thread thread2 = new Thread (new Runnable () {@Override public void run () {try {doprint (' thread 2 get lock. ')
   );
   Do123 ();   
  Doprint ("Thread 2 end.");
  catch (Interruptedexception e) {doprint ("Thread 2 is interrupted.");
 
 }
  }
 });
 Thread1.setname ("Thread1");
 Thread2.setname ("Thread2");
 Thread1.start ();
 try {thread.sleep (100);//Wait one will allow Thread1 to perform a catch (Interruptedexception e) {e.printstacktrace () before thread2.
 } thread2.start (); private static void do123 () throWS interruptedexception {lock.lockinterruptibly ();
 Doprint (Thread.CurrentThread (). GetName () + "is locked.");
  try {doprint (Thread.CurrentThread (). GetName () + "doSoming1 ...");

  Thread.Sleep (5000);//Wait a few seconds to easily view the sequence of threads Doprint (Thread.CurrentThread (). GetName () + "doSoming2 ...");
 Doprint (Thread.CurrentThread (). GetName () + "is finished.");
 finally {Lock.unlock ();
 } private static void Doprint (String text) {System.out.println (New Date ()). toLocaleString () + ":" + text);

 }
}

There are two threads in the code above, the THREAD1 started earlier than Thread2, and to see the lock in the process of locking the code to sleep for 5 seconds, so you can feel the previous two threads into the acquisition lock process. The resulting code runs as follows:

2016-9-28 15:12:56:thread 1 Get lock.
2016-9-28 15:12:56:thread1 is locked.
2016-9-28 15:12:56:thread1 doSoming1 .....
2016-9-28 15:12:56:thread 2 get lock.
2016-9-28 15:13:01:thread1 doSoming2 .....
2016-9-28 15:13:01:thread1 is finished.
2016-9-28 15:13:01:thread1 is unloaded.
2016-9-28 15:13:01:thread2 is locked.
2016-9-28 15:13:01:thread2 doSoming1 .....
2016-9-28 15:13:01:thread 1 end.
2016-9-28 15:13:06:thread2 doSoming2 .....
2016-9-28 15:13:06:thread2 is finished.
2016-9-28 15:13:06:thread2 is unloaded.
2016-9-28 15:13:06:thread 2 end.

You can see, thread1 first get the lock, a thread2 also to take the lock, but this time Thread1 has been occupied, so Thread2 until Thread1 released the lock to get the lock.

* * This code shows that the thread behind the lockinterruptibly to acquire the lock needs to wait for the lock to be released before the lock can be obtained. * * But there is no interruptible feature here, add some code to this:

Thread2.start ();
try {
 thread.sleep (1000);  
} catch (Interruptedexception e) {
 e.printstacktrace ();
} 
1 seconds after the thread 2 interrupt
thread2.interrupt ();

After the thread2 start call the Thread2 interrupt method, OK, run the code to see the results:

2016-9-28 15:16:46:thread 1 Get lock.
2016-9-28 15:16:46:thread1 is locked.
2016-9-28 15:16:46:thread1 doSoming1 .....
2016-9-28 15:16:46:thread 2 get lock.
2016-9-28 15:16:47:thread 2 is interrupted. <--directly responds to thread interrupts
2016-9-28 15:16:51:thread1 doSoming2 .....
2016-9-28 15:16:51:thread1 is finished.
2016-9-28 15:16:51:thread1 is unloaded.
2016-9-28 15:16:51:thread 1 end.
As you can see in the previous code, THREAD2 is waiting for the thread1 to release the lock, but Thread2 has broken itself, and the code behind THREAD2 will not continue.

Readwritelock

As the name implies is read-write lock, this reading-writing lock application scenario can be understood, such as a wave of data most of the time is to provide read, and only a small number of write operations, then if the use of mutual exclusion lock will lead to the lock between the threads of competition. If you can read it, you will be able to lock it once you write it. Such a change is a good solution to this problem, so that the read operation can improve the performance of reading, and will not affect the operation of the write.

A resource can be accessed by multiple readers or accessed by a writer, both of which cannot be performed concurrently.

This is an abstract interface for reading and writing locks, defining a read lock and a write lock.

Public interface Readwritelock {
  /**
   * Returns the lock used for reading.
   *
   @return The lock used for reading *
  /Lock Readlock ();

  /**
   * Returns the lock used for writing.
   *
   @return The lock used for writing *
  /Lock Writelock ();
}

There is a reentrantreadwritelock implementation in the JDK, which is a reentrant read-write lock. Reentrantreadwritelock can be constructed as either fair or inequitable. If not explicitly specified at construction time, an unjust lock is created by default. In an unfair lock mode, the order in which the threads are accessed is either indeterminate or intrusive, and can be demoted by the writer to the reader, but the reader cannot be upgraded to a writer.

If it is a fair lock mode, then the option is given to the longest-waiting thread, and if a read thread acquires the lock, a write thread requests a write lock, and then the fetch of the read lock is no longer received until the write operation completes.

Simple code Analysis in Reentrantreadwritelock actually maintains a sync lock, but it looks semantically like a read lock and write lock. Take a look at its constructor:

Public Reentrantreadwritelock (Boolean fair) {
  sync = Fair New Fairsync (): New Nonfairsync ();
  ReaderLock = new Readlock (this);
  WriterLock = new Writelock (this);
}

Read lock constructor
protected Readlock (Reentrantreadwritelock Lock) {
  sync = lock.sync;
}
Write lock constructor
protected Writelock (Reentrantreadwritelock Lock) {
  sync = lock.sync;
}

You can see that the Reentrantreadwritelock Sync lock object is actually a reference to the read/write lock at construction time. And this sync class is an internal class of Reentrantreadwritelock. In short, read/write locks are done through sync. How is it to collaborate on these two relationships?

Lock method for read lock public
void Lock () {
  sync.acquireshared (1);
}

Lock method for write lock public
void Lock () {
  sync.acquire (1);
}

The main difference is that the read lock acquires a shared lock, while a write lock acquires an exclusive lock. Here's a point to mention, Reentrantreadwritelock. In order to ensure reentrant, both shared and exclusive locks must support the hold count and the number of reentrant. While the reentrantlock is stored using state, and state can only save one cosmetic value, in order to be compatible with the two-lock problem, it divides the number of threads with a high 16-bit and a low 16-bit amount, or the number of threads that have an exclusive lock, or a reentrant count.

Other

Wrote a big piece of feeling to write down too long, there are some more useful locks:

Countdownlatch

is to set up a counter that is held at the same time, and when the caller calls the Countdownlatch await method, if the current counter is not 0, the call to the Countdownlatch release method can reduce the count, The caller who called await until the count is 0 o'clock will unblock it.

Semaphone

Semaphores are a form of authorization, such as setting up 100 licenses, so that 100 threads can hold a lock at the same time, and if this amount is exceeded, the failure is returned.

Thank you for reading this article, I hope to help you, thank you for your support for this site!

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.