In Java concurrent programming, use ReentrantLock to replace the synchronized keyword primitive.

Source: Internet
Author: User
Tags finally block

In Java concurrent programming, use ReentrantLock to replace the synchronized keyword primitive.
Tags: the Concurrent library package introduced by Java 5 provides ReentrantLock that can be reloaded into the synchronization lock to replace the synchronized keyword primitive, and provides better performance and more powerful functions. The usage is also simple: public final ReentrantLock lock = new ReentrantLock ();...... try {lock. lock (); // enter the synchronization content ....} finally {lock. unlock (); // It must be unlocked in the finally block. Otherwise, if an exception occurs and the unlock fails to be executed, it will remain locked .} Synchronized primitives and ReentrantLock have no difference in general, but in very complex synchronization applications, consider using ReentrantLock, especially when encountering the following two requirements. 1. A thread needs to be interrupted while waiting for control of a lock. some Condition applications in wait-policy and ReentrantLock need to be processed separately to control which thread of wait y is required. with the fair lock function, every incoming thread will wait in the queue for the first case. There are two lock mechanisms for ReentrantLock, which ignore the interrupt lock and respond to the interrupt lock, this gives us great flexibility. For example, if A and B2 threads compete for the lock, thread A gets the lock and thread B waits, but thread A has too many things to handle at this time, that is, it never returns, the B-thread may be unable to wait. If you want to interrupt yourself and stop waiting for the lock, you can handle other things. At this time, ReentrantLock provides two mechanisms. First, the B thread interrupts itself (or other threads interrupt it), but the ReentrantLock does not respond and keeps the B thread waiting. How can you interrupt it, I am all ears (this is the synchronized primitive); second, the B thread interrupts itself (or other threads interrupt it), the ReentrantLock handles the interrupt, and no longer waits for the lock to come, give up. (If you do not understand the java interrupt mechanism, please refer to the relevant information and look back at this article. 80% of people do not really understand what java interrupt is) here we will do an experiment. First, we will create a Buffer class, which has read and write operations. In order not to read dirty data, the write and read operations need to be locked. We will first use the synchronized primitive to lock, as follows:

Public class Buffer {private Object lock; public Buffer () {lock = this;} public void write () {synchronized (lock) {long startTime = System. currentTimeMillis (); System. out. println ("start writing data to this buff... "); For (;) // simulate a long time to process {if (System. currentTimeMillis ()-startTime> Integer. MAX_VALUE) break;} System. out. println ("finished") ;}} public void read () {synchronized (lock) {System. out. println ("read data from this buff ");}}}

 

Next, let's define two threads, one thread to write and one thread to read.
Public class Writer extends Thread {private Buffer buff; public Writer (Buffer buff) {this. buff = buff;} @ Override public void run () {buff. write () ;}} public class Reader extends Thread {private Buffer buff; public Reader (Buffer buff) {this. buff = buff;} @ Override public void run () {buff. read (); // It is estimated that the System will be blocked all the time. out. println ("read ended ");}}

 

Well, write a Main program to test it. We intend to "write" first, and then let "read" Wait. The "write" time is infinite, so we can see if "read" can give up.
Public class Test {public static void main (String [] args) {Buffer buff = new Buffer (); final Writer writer = new Writer (buff ); final Reader reader = new Reader (buff); writer. start (); reader. start (); new Thread (new Runnable () {@ Override public void run () {long start = System. currentTimeMillis (); for (;) {// wait for 5 seconds to interrupt read if (System. currentTimeMillis ()-start> 5000) {System. out. println ("No, try to interrupt"); reader. interrupt (); break ;}}}}). start ();}}

 

We expect the "read" thread to exit the wait lock, but this is counterproductive. Once the read thread finds itself unable to get the lock, it continues to wait. Even if it waits for death, it will not get the lock, because it takes 2.1 billion seconds for the write thread to complete T_T, even if we interrupt it, it will not respond, it seems to be waiting for death. At this time, ReentrantLock provides a mechanism for us to respond to the interruption, so that "read" can be stretched and bent, and brave enough to give up waiting for the lock. Let's rewrite the Buffer class. It's called BufferInterruptibly, which can interrupt the cache.
Import java. util. concurrent. locks. reentrantLock; public class BufferInterruptibly {private ReentrantLock lock = new ReentrantLock (); public void write () {lock. lock (); try {long startTime = System. currentTimeMillis (); System. out. println ("start writing data to this buff... "); For (;) // simulate a long time to process {if (System. currentTimeMillis ()-startTime> Integer. MAX_VALUE) break;} System. out. println ("finally finished");} finally {lock. unlock () ;}} public void read () throws InterruptedException {lock. lockInterruptibly (); // note that here, you can respond to the interrupt try {System. out. println ("read data from this buff");} finally {lock. unlock ();}}}

 

Of course, you must modify the response of reader and writer.
Public class Reader extends Thread {private BufferInterruptibly buff; public Reader (BufferInterruptibly buff) {this. buff = buff;} @ Override public void run () {try {buff. read (); // you can receive an exception that interrupts your System and exit} catch (InterruptedException e) {System. out. println ("I do not read");} System. out. println ("read ended") ;}} public class Writer extends Thread {private BufferInterruptibly buff; public Writer (BufferInterruptibly buff) {this. buff = buff;} @ Override public void run () {buff. write () ;}} public class Test {public static void main (String [] args) {BufferInterruptibly buff = new BufferInterruptibly (); final Writer writer = new Writer (buff ); final Reader reader = new Reader (buff); writer. start (); reader. start (); new Thread (new Runnable () {@ Override public void run () {long start = System. currentTimeMillis (); for (;) {if (System. currentTimeMillis ()-start> 5000) {System. out. println ("No, try to interrupt"); reader. interrupt (); break ;}}}}). start ();}}

 


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.