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:
- public class LockTest {
- public static void main(String[] args) {
- final Outputter1 output = new Outputter1();
- new Thread() {
- public void run() {
- output.output("zhangsan");
- };
- }.start();
- new Thread() {
- public void run() {
- output.output("lisi");
- };
- }.start();
- }
- }
- class Outputter1 {
- private Lock lock = new ReentrantLock();//Lock object
- public void output(String name) {
- //TODO Thread Output Method
- lock.lock();//Get lock
- try {
- for(int i = 0; i < name.length(); i++) {
- System.out.print(name.charAt(i));
- }
- } finally {
- lock.unlock();//Release lock
- }
- }
- }
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:
- public class ReadWriteLockTest {
- public static void main(String[] args) {
- final Data data = new Data();
- for (int i = 0; i < 3; i++) {
- new Thread(new Runnable() {
- public void run() {
- for (int j = 0; j < 5; j++) {
- data.set(new Random().nextInt(30));
- }
- }
- }).start();
- }
- for (int i = 0; i < 3; i++) {
- new Thread(new Runnable() {
- public void run() {
- for (int j = 0; j < 5; j++) {
- data.get();
- }
- }
- }).start();
- }
- }
- }
- class Data {
- private int data;//Shared data
- public void set(int data) {
- System.out.println(Thread.currentThread().getName() + "Ready to write data");
- try {
- Thread.sleep(20);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- this.data = data;
- System.out.println(Thread.currentThread().getName() + "Write in" + this.data);
- }
- public void get() {
- System.out.println(Thread.currentThread().getName() + "Ready to read data");
- try {
- Thread.sleep(20);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "read" + this.data);
- }
- }
Partial output results:
- Thread-1 is ready to write data.
- Thread-3 Reads Data
- Thread-2 is ready to write data.
- Thread-0 is ready to write data.
- Thread-4 Reads Data
- Thread-5 Reads Data
- Thread-2 Writes 12
- Thread-4 Read 12
- Thread-5 Read 5
- 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:
- public synchronized void set(int data) {...}
- public synchronized void get() {...}
Partial output results:
- Thread-0 is ready to write data.
- Thread-0 Writes 9
- Thread-5 Reads Data
- Thread-5 Read 9
- Thread-5 Reads Data
- Thread-5 Read 9
- Thread-5 Reads Data
- Thread-5 Read 9
- Thread-5 Reads Data
- 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:
- class Data {
- private int data;//Sharing data
- private ReadWriteLock rwl = new ReentrantReadWriteLock();
- public void set(int data) {
- rwl.writeLock().lock();//Access Write Lock
- try {
- System.out.println(Thread.currentThread().getName() + "Ready to write data");
- try {
- Thread.sleep(20);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- this.data = data;
- System.out.println(Thread.currentThread().getName() + "Write in" + this.data);
- } finally {
- rwl.writeLock().unlock();//Release write locks
- }
- }
- public void get() {
- rwl.readLock().lock();//Access Read Lock
- try {
- System.out.println(Thread.currentThread().getName() + "Ready to read data");
- try {
- Thread.sleep(20);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "read" + this.data);
- } finally {
- rwl.readLock().unlock();//Release read lock
- }
- }
- }
Partial output results:
- Thread-4 Reads Data
- Thread-3 Reads Data
- Thread-5 Reads Data
- Thread-5 Read 18
- Thread-4 Read 18
- Thread-3 Read 18
- Thread-2 is ready to write data.
- Thread-2 Writes 6
- Thread-2 is ready to write data.
- Thread-2 Writes 10
- Thread-1 is ready to write data.
- Thread-1 writes 22