This article mainly introduces the use of Android multi-threaded synchronization locks. It is shared with you. The details are as follows:
1. Synchronized keyword synchronized
For Java, the most commonly used synchronization mechanism is the synchronized keyword, which is a rough language-based lock that can act on objects, functions, and classes. Each object has only one lock, and whoever can get this lock will have access rights. When synchronized acts on a function, the locked object is actually the object, and the locked object is the object of the class where the function is located. When synchronized acts on class, it is the Class class that is locked, not a specific object.
public class SynchronizedClass { public synchronized void syncMethod(){ //Code } public void syncThis(){ synchronized (this){ //Code } } public void syncClassMethod(){ synchronized (){ //Code } } public synchronized static void syncStaticMethod(){ //Code } }
The above demonstrates synchronization methods, synchronization blocks, synchronization class objects, and synchronization static methods. The first two types of lock are objects, while the last two types of lock are class objects. For class objects, its function is to prevent multiple threads from accessing code blocks with synchronized locks at the same time, while synchronized acts on the reference object to prevent other threads from accessing synchronized code blocks or functions in the same object.
2. Display lock———ReentrankLock and Condition
ReentrankLock achieves the same semantics compared to the built-in lock synchronized, but has more flexibility.
(1) Flexibility to obtain and release.
(2) Rotary training lock and timing lock.
(3) Fairness.
Basic operations:
lock(): acquire lock
tryLock(): Try to acquire the lock
tryLock(long timeout,TimeUnit unit): Try to acquire the lock. If the specified time is still not available, then the timeout is timed.
unlock(): release the lock
newCondition(): Acquire the lock's Condition
The general combination of using ReentrantLock is lock, tryLock, and unLock. It should be noted that you must not forget to call unlock to release the lock, and be responsible for the problems that may cause deadlock. The commonly used forms of ReentrantLock are as follows:
public class ReentrantLockDemo { Lock lock = new ReentrantLock(); public void doSth(){ (); try { //Perform certain operations }finally { (); } } }
It should be noted that the lock must be released in finally open, otherwise, if the protected code throws an exception, the lock may never be released! !
There is also an important function in the ReentrantLock class newCondition(). This function user obtains a condition on Lock(), which means that Condition is bound to Lock. Condition is used to implement communication between threads, and it is to solve the problem of difficulty in using(), nofity(), nofityAll().
The method of Condition is as follows:
await() : thread waiting
await(int time,TimeUnit unit) The thread waits for a specific time, and the time exceeds the time is timeout.
signal() randomly wakes up a waiting thread
signal() wakes up all waiting threads
Sample code:
public class MyArrayBlockingQueue<T> { // Data array private final T[] items; private final Lock lock = new ReentrantLock(); private Condition notFull = (); private Condition notEmpty = () ; // Header index private int head; // tail index private int tail ; // Number of data private int count; public MyArrayBlockingQueue(int maxSize) { items = (T[]) new Object[maxSize]; } public MyArrayBlockingQueue(){ this(10); } public void put(T t){ (); try { while(count == getCapacity()){ ("The data is full, waiting"); (); } items[tail] =t ; if(++tail ==getCapacity()){ tail = 0; } ++count; ();//Wake up the thread waiting for data } catch (InterruptedException e) { (); }finally { (); } } public int getCapacity(){ return ; } public T take(){ (); try { while(count ==0){ ("No data yet, wait"); // Which thread calls await() and which thread blocks (); } T ret = items[head]; items[head] = null ; if(++head == getCapacity()){ head =0 ; } --count; (); return ret ; } catch (InterruptedException e) { (); }finally { (); } return null ; } public int size(){ (); try { return count; }finally { (); } } public static void main(String[] args){ MyArrayBlockingQueue<Integer> aQueue = new MyArrayBlockingQueue<>(); (3); (24); for(int i=0;i<5;i++){ (()); } ("Finish"); } }
Execution results:
3
24
No data yet, wait
3. Semaphore
Semaphore is a counting semaphore, and its essence is a "shared lock". Semaphore maintains a semaphore license set, and threads can obtain the semaphore license by calling acquire(). When a license is available in the semaphore, the thread can obtain the license; otherwise the thread must wait until the license is available. A thread can release the semaphore license it holds by release().
Example:
public class SemaphoreTest { public static void main(String[] args){ final ExecutorService executorService = (3); final Semaphore semaphore = new Semaphore(3); List<Future> futures = new ArrayList<>(); for (int i = 0; i < 5; i++) { Future<?> submit = (new Runnable() { @Override public void run() { try { (); ("Remaining Permits: " + ()); (3000); (); } catch (InterruptedException e) { (); } } }); (submit); } } }
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.