1. Preface
This paper introduces the use of Lock object in Java5, which can also achieve synchronization effect, and is more convenient and flexible to use, mainly including the use of ReentrantLock class and the use of ReentrantReadWriteLock class.
2. Using the ReentrantLock class
1. In java multi-threading, synchronized keywords can be used to synchronize and mutually exclusive threads, but the new ReentrantLock in JDK1.5 also achieves the same effect and is more powerful in terms of extensions, such as sniffing locks, multi-branch notifications, and more flexible in use than synchronized.
2. Threads calling lock.lock() code have an Object Monitor, which means that locks hold object locks and depend on the existence of instances of that class.
public class MyService { private Lock lock=new ReentrantLock(); public void testMethod(){ lock.lock(); for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()+(i+1)); } lock.unlock(); } }
3. The keyword synchronized, combined with the wait() and notify()/notifyAll() methods, implements the wait/notification mode, and the ReentrantLock class can do the same, but with the help of the Condition object.
public class Myservice { private Lock lock=new ReentrantLock(); private Condition condition=lock.newCondition(); //wait for public void waitMethod(){ try { lock.lock(); System.out.println("A"); condition.await();//Called Condition Of await The wait method also needs to be in the synchronization method, otherwise an error will be reported System.out.println("B"); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } //awaken public void signal(){ try { lock.lock(); System.out.println("Start waking up now..."); condition.signal(); }finally { lock.unlock(); } } }
4. Use multiple Condition objects to implement selective notifications between threads.
public class MyService { private Lock lock=new ReentrantLock(); //By defining multiple Condition Implement selective notifications,You can wake up a specified kind of thread, which is //A convenient way to control the behavior of some threads private Condition conditionA=lock.newCondition(); private Condition conditionB=lock.newCondition(); public void awaitA(){ try { lock.lock(); System.out.println("awaitA begin"); conditionA.await(); System.out.println("awaitA end"); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } public void awaitB(){ try { lock.lock(); System.out.println("awaitB begin"); conditionB.await(); System.out.println("awaitB end"); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } public void signalA(){ try { lock.lock(); System.out.println("Start waking up now awaitA"); conditionA.signalAll(); }finally { lock.unlock(); } } public void signalB(){ try { lock.lock(); System.out.println("Start waking up now awaitB"); conditionB.signalAll(); }finally { lock.unlock(); } } }
public class Run { public static void main(String[] args) throws InterruptedException { MyService myService=new MyService(); Thread threadA=new Thread(){ @Override public void run() { super.run(); myService.awaitA(); } }; Thread threadB=new Thread(){ @Override public void run() { super.run(); myService.awaitB(); } }; threadA.start(); threadB.start(); Thread.sleep(1000); myService.signalA(); Thread.sleep(1000); myService.signalB(); } }
5. Fair locks and unfair locks
public class Service { private Lock lock; public Service(boolean isFair) { //Create a fair lock this way(true)And unfair locks(false) lock=new ReentrantLock(isFair); } public void methodA(){ try { lock.lock(); System.out.println(Thread.currentThread().getName()+"Running"); }finally { lock.unlock(); } } }
public class Run { public static void main(String[] args) { final Service service=new Service(true); Runnable runnable=new Runnable() { @Override public void run() { service.methodA(); } }; Thread[] threads=new Thread[10]; for (int i=0;i<10;i++){ threads[i]=new Thread(runnable); threads[i].setName("thread"+(i+1)); threads[i].start(); } } }
6. Introduction of ReentrantLock's common methods
(1) int getHoldCount() queries the number of times the current thread holds this lock, that is, the number of lock method calls in the thread.
(2) int getQueueLength() returns the estimated number of threads waiting for this Lock, such as five threads, one thread holding the Lock for execution, and the call to this method returns 4.This value is only an estimated number because the number of threads can change dynamically as this method traverses the internal data structure.This method is used to monitor the state of the system and does not require synchronous control.
(3) int getWaitQueueLength(Condition condition) returns an estimate of the thread waiting for a given condition condition condition condition associated with this lock, such as five threads, each executing the await() method of the same condition object, and the value returned by calling this method is 5.
public class Service { private ReentrantLock lock=new ReentrantLock(); private Condition condition=lock.newCondition(); public void methodA(){ try { lock.lock(); System.out.println("A getHoldCount call lock Number of times=>"+lock.getHoldCount()); Thread.sleep(2000); System.out.println("A getQueueLength Number of threads waiting=>"+lock.getQueueLength()); condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } //test getWaitQueueLength Method public Integer methodC(){ try { lock.lock(); return lock.getWaitQueueLength(condition); }finally { lock.unlock(); } } }
public class Run{ public static void main(String[] args) throws InterruptedException { Service service=new Service(); Runnable runnable=new Runnable() { @Override public void run() { service.methodA(); } }; Thread[] threads=new Thread[5]; for (int i=0;i<5;i++){ threads[i]=new Thread(runnable); threads[i].start(); } Thread.sleep(1000); System.out.println("Executed the same Condition Object's await()Threads are:"+service.methodC()); } }
(4) boolean hasQueuedThread(Thread thread) queries whether the specified thread is waiting to acquire this lock.
(5) boolean hasQueuedThreads() queries whether a thread is waiting to acquire this lock.
(6) boolean hasWaiters(Condition condition) queries whether a thread is waiting for a condition condition associated with this lock
(7) boolean isFair() judges whether the lock is fair.
(8) boolean isHelpByCurrentThread() queries if the current thread holds this lock.
(9) boolean isLocked() queries whether the lock is maintained by any thread.
(10) void lockInterruptibly() Acquires a lock if the current thread has not been interrupted, or an exception if it has been interrupted.
(11) boolean tryLock() acquires the lock only if it was not locked by another thread at the time of the call.
(12) boolean tryLock(long timeout,TimeUnit unit) acquires a lock if it is not held by another thread within a given wait time and the current thread is not interrupted.
public class Service { private ReentrantLock lock=new ReentrantLock(); private Condition condition=lock.newCondition(); //test lockInterruptibly public void methodA(){ try { lock.lockInterruptibly(); System.out.println("methodA=>"+Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); }finally { if (lock.isHeldByCurrentThread()){//Release if the current thread remains locked on this lock lock.unlock(); } } } //test tryLock public void methodB(){ if (lock.tryLock()){ System.out.println(Thread.currentThread().getName()+"Acquire locks"); }else{ System.out.println(Thread.currentThread().getName()+"No Lock Acquired"); } } }
public class Run { public static void main(String[] args) throws InterruptedException { Service service=new Service(); Runnable runnable=new Runnable() { @Override public void run() { service.methodA(); service.methodB(); } }; Thread threadA=new Thread(runnable); threadA.setName("A"); threadA.start(); Thread.sleep(1000); Thread threadB=new Thread(runnable); threadB.setName("B"); threadB.start(); threadB.interrupt(); } }
(13) lock.awaitUninterruptibly(): This thread will not be interrupted until other threads call the signal() or signalAll() methods.
(14) lock.awaitUntil(Date date): This thread will sleep until:
- It was interrupted
- Other threads call the singal() or signalAll() method on this condition
- The specified date has arrived
3. Use the ReentrantReadWriteLock class
public class Read { private ReentrantReadWriteLock lock=new ReentrantReadWriteLock(); public void read(){ try { lock.readLock().lock(); System.out.println(Thread.currentThread().getName()+"Reading"+System.currentTimeMillis()); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.readLock().unlock(); } } }
public class Run { public static void main(String[] args) { Read read=new Read(); Runnable runnable=new Runnable() { @Override public void run() { read.read(); } }; Thread[] threads=new Thread[10]; for (int i=0;i<10;i++){ threads[i]=new Thread(runnable); threads[i].start(); //As a result, you can see that all threads are entering at almost the same time lock()Method //Later code, read not mutually exclusive, can improve the efficiency of the program, allow //Multiple threads executing simultaneously lock()Code behind method } } }
public class Write { private ReentrantReadWriteLock lock=new ReentrantReadWriteLock(); public void write(){ try { lock.writeLock().lock(); System.out.println(Thread.currentThread().getName()+"Writing"+System.currentTimeMillis()); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.writeLock().unlock(); } } }
public class Run { public static void main(String[] args) { Write write=new Write(); Runnable runnable=new Runnable() { @Override public void run() { write.write(); } }; Thread[] threads=new Thread[10]; for (int i=0;i<10;i++){ threads[i]=new Thread(runnable); threads[i].start(); //As a result, you can see that all threads run every two seconds, write and write are mutually exclusive, and threads run synchronously } } }
In addition, writing, reading and writing are mutually exclusive, so no example is given.In short, as long as "write" operations occur, they are mutually exclusive!