The Use of Three Locks in Android

Keywords: Java

I. synchronized

slightly

 

Two, lock

Lock is java.util.concurrent.locks Under the package, Lock implementations provide a wider range of locking operations than can be obtained using synchronized methods and statements, because Lock can lock any piece of code:

  1. public class LockTest {  
  2.     public static void main(String[] args) {  
  3.         final Outputter1 output = new Outputter1();  
  4.         new Thread() {  
  5.             public void run() {  
  6.                 output.output("zhangsan");  
  7.             };  
  8.         }.start();        
  9.         new Thread() {  
  10.             public void run() {  
  11.                 output.output("lisi");  
  12.             };  
  13.         }.start();  
  14.     }  
  15. }  
  16. class Outputter1 {  
  17.     private Lock lock = new ReentrantLock();//Lock object  
  18.     public void output(String name) {  
  19.         //TODO Thread Output Method  
  20.         lock.lock();//Get lock  
  21.         try {  
  22.             for(int i = 0; i < name.length(); i++) {  
  23.                 System.out.print(name.charAt(i));  
  24.             }  
  25.         } finally {  
  26.             lock.unlock();//Release lock  
  27.         }  
  28.     }  
  29. }  

In this way, we can achieve the same synchronization effect as sychronized. It should be noted that the lock is automatically released after the code is executed by using sychronized modification method or statement block, and we need to release the lock manually with Lock. So in order to ensure that the lock is finally released (abnormal situation), we should put the mutex in try and the release lock in final.

 

ReadWriteLock

If this is Lock, then it can't be a more perfect way to deal with synchronization problems. ReadWriteLock is introduced below. We will have a demand that when we read and write data, in order to ensure the consistency and integrity of data, we need to read and write mutually exclusive and write mutually exclusive, but read and read do not need to be mutually exclusive, so read and read do not need to be mutually exclusive. Non-mutually exclusive performance is better. Let's look at code prototypes that do not consider mutually exclusive situations:

  1. public class ReadWriteLockTest {  
  2.     public static void main(String[] args) {  
  3.         final Data data = new Data();  
  4.         for (int i = 0; i < 3; i++) {  
  5.             new Thread(new Runnable() {  
  6.                 public void run() {  
  7.                     for (int j = 0; j < 5; j++) {  
  8.                         data.set(new Random().nextInt(30));  
  9.                     }  
  10.                 }  
  11.             }).start();  
  12.         }         
  13.         for (int i = 0; i < 3; i++) {  
  14.             new Thread(new Runnable() {  
  15.                 public void run() {  
  16.                     for (int j = 0; j < 5; j++) {  
  17.                         data.get();  
  18.                     }  
  19.                 }  
  20.             }).start();  
  21.         }  
  22.     }  
  23. }  
  24. class Data {      
  25.     private int data;//Shared data  
  26.     public void set(int data) {  
  27.         System.out.println(Thread.currentThread().getName() + "Ready to write data");  
  28.         try {  
  29.             Thread.sleep(20);  
  30.         } catch (InterruptedException e) {  
  31.             e.printStackTrace();  
  32.         }  
  33.         this.data = data;  
  34.         System.out.println(Thread.currentThread().getName() + "Write in" + this.data);  
  35.     }     
  36.     public void get() {  
  37.         System.out.println(Thread.currentThread().getName() + "Ready to read data");  
  38.         try {  
  39.             Thread.sleep(20);  
  40.         } catch (InterruptedException e) {  
  41.             e.printStackTrace();  
  42.         }  
  43.         System.out.println(Thread.currentThread().getName() + "read" + this.data);  
  44.     }  
  45. }  


Partial output results:

  1. Thread-1 is ready to write data.
  2. Thread-3 Reads Data
  3. Thread-2 is ready to write data.
  4. Thread-0 is ready to write data.
  5. Thread-4 Reads Data
  6. Thread-5 Reads Data
  7. Thread-2 Writes 12
  8. Thread-4 Read 12
  9. Thread-5 Read 5
  10. Thread-1 writes 12


To achieve write and write mutexes, read and write mutexes, read and read mutexes, add sychronized modifiers to set and get methods:

  1. public synchronized void set(int data) {...}      
  2. public synchronized void get() {...}  

 

Partial output results:

  1. Thread-0 is ready to write data.
  2. Thread-0 Writes 9
  3. Thread-5 Reads Data
  4. Thread-5 Read 9
  5. Thread-5 Reads Data
  6. Thread-5 Read 9
  7. Thread-5 Reads Data
  8. Thread-5 Read 9
  9. Thread-5 Reads Data
  10. Thread-5 Read 9


We find that although write and write are mutually exclusive, read and write are mutually exclusive, but read and read are mutually exclusive, can not be executed concurrently, and the efficiency is low. Read and write locks are used to implement the code as follows:

  1. class Data {      
  2.     private int data;//Sharing data  
  3.     private ReadWriteLock rwl = new ReentrantReadWriteLock();     
  4.     public void set(int data) {  
  5.         rwl.writeLock().lock();//Access Write Lock  
  6.         try {  
  7.             System.out.println(Thread.currentThread().getName() + "Ready to write data");  
  8.             try {  
  9.                 Thread.sleep(20);  
  10.             } catch (InterruptedException e) {  
  11.                 e.printStackTrace();  
  12.             }  
  13.             this.data = data;  
  14.             System.out.println(Thread.currentThread().getName() + "Write in" + this.data);  
  15.         } finally {  
  16.             rwl.writeLock().unlock();//Release write locks  
  17.         }  
  18.     }     
  19.     public void get() {  
  20.         rwl.readLock().lock();//Access Read Lock  
  21.         try {  
  22.             System.out.println(Thread.currentThread().getName() + "Ready to read data");  
  23.             try {  
  24.                 Thread.sleep(20);  
  25.             } catch (InterruptedException e) {  
  26.                 e.printStackTrace();  
  27.             }  
  28.             System.out.println(Thread.currentThread().getName() + "read" + this.data);  
  29.         } finally {  
  30.             rwl.readLock().unlock();//Release read lock  
  31.         }  
  32.     }  
  33. }  


Partial output results:

  1. Thread-4 Reads Data
  2. Thread-3 Reads Data
  3. Thread-5 Reads Data
  4. Thread-5 Read 18
  5. Thread-4 Read 18
  6. Thread-3 Read 18
  7. Thread-2 is ready to write data.
  8. Thread-2 Writes 6
  9. Thread-2 is ready to write data.
  10. Thread-2 Writes 10
  11. Thread-1 is ready to write data.
  12. Thread-1 writes 22


 

In this way, write and write mutually exclusive, read and write mutually exclusive, but read and read mutually exclusive, improve code efficiency.

Posted by mithril on Sat, 25 May 2019 10:19:02 -0700