Android多线程之同步锁的使用
本文主要介紹了Android多線程之同步鎖的使用,分享給大家,具體如下:
一、同步機制關鍵字synchronized
對于Java來說,最常用的同步機制就是synchronized關鍵字,他是一種基于語言的粗略鎖,能夠作用于對象、函數、class。每個對象都只有一個鎖,誰能夠拿到這個鎖誰就有訪問權限。當synchronized作用于函數時,實際上鎖的也是對象,鎖定的對象就是該函數所在類的對象。而synchronized作用于class時則是鎖的這個Class類,并非具體對象。
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class SynchronizedClass { ??public synchronized void syncMethod(){ ????//代碼 ??} ? ??public void syncThis(){ ????synchronized (this){ ??????//代碼 ????} ??} ? ??public void syncClassMethod(){ ????synchronized (SynchronizedClass.class){ ??????//代碼 ????} ??} ? ??public synchronized static void syncStaticMethod(){ ????//代碼 ??} } |
上面演示了同步方法、同步塊、同步class對象、同步靜態方法。前2種鎖的是對象,而后兩種鎖的是class對象。對于class對象來說,它的作用是防止多個線程同時訪問添加了synchronized鎖的代碼塊,而synchronized作用于引用對象是防止其他線程訪問同一個對象中synchronized代碼塊或者函數。
二、顯示鎖———-ReentrankLock和Condition
ReentrankLock 和內置鎖synchronized相比,實現了相同的語義,但是更具有更高的靈活性。
(1)獲得和釋放的靈活性。
(2)輪訓鎖和定時鎖。
(3)公平性。
基本操作:
lock(): 獲取鎖
tryLock(): 嘗試獲取鎖
tryLock(long timeout,TimeUnit unit): 嘗試獲取鎖,如果到了指定的時間還獲取不到,那么超時。
unlock(): 釋放鎖
newCondition(): 獲取鎖的 Condition
使用ReentrantLock的一般組合是 lock、tryLock、與unLock成對出現,需要注意的是,千萬不要忘記調用unlock來釋放鎖,負責可能引發死鎖的問題。ReentrantLock的常用形式如下所示:
?
| 1 2 3 4 5 6 7 8 9 10 11 12 | public class ReentrantLockDemo { ??Lock lock = new ReentrantLock(); ? ??public void doSth(){ ????lock.lock(); ????try { ??????//執行某些操作 ????}finally { ??????lock.unlock(); ????} ??} } |
需要注意的是,lock必須在finally開中釋放,否則,如果受保護的代碼拋出異常,鎖就可能永遠得不到釋放!!
ReentrantLock類中還有一個重要的函數newCondition(),該函數用戶獲取Lock()上的一個條件,也就是說Condition與Lock綁定。Condition用于實現線程間的通信,他是為了解決Object.wait(),nofity(),nofityAll() 難以使用的問題。
Condition的方法如下:
await() : 線程等待
await(int time,TimeUnit unit) 線程等待特定的時間,超過的時間則為超時。
signal() 隨機喚醒某個等待線程
signal() 喚醒所有等待中的線程
示例代碼:
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | public class MyArrayBlockingQueue<T> { ? //? 數據數組 ??private final T[] items; ? ??private final Lock lock = new ReentrantLock(); ? ??private Condition notFull = lock.newCondition(); ??private Condition notEmpty = lock.newCondition() ; ? //? 頭部索引 ??private int head; //? 尾部索引 ??private int tail ; //? 數據的個數 ??private int count; ? ??public MyArrayBlockingQueue(int maxSize) { ????items = (T[]) new Object[maxSize]; ??} ? ??public MyArrayBlockingQueue(){ ????this(10); ??} ? ??public void put(T t){ ????lock.lock(); ????try { ??????while(count == getCapacity()){ ????????System.out.println("數據已滿,等待"); ????????notFull.await(); ??????} ??????items[tail] =t ; ??????if(++tail ==getCapacity()){ ????????tail = 0; ??????} ??????++count; ??????notEmpty.signalAll();//喚醒等待數據的線程 ????} catch (InterruptedException e) { ??????e.printStackTrace(); ????}finally { ??????lock.unlock(); ????} ??} ? ??public int getCapacity(){ ????return items.length ; ??} ? ??public T take(){ ????lock.lock(); ????try { ??????while(count ==0){ ????????System.out.println("還沒有數據,等待"); ????????//哪個線程調用await()則阻塞哪個線程 ????????notEmpty.await(); ??????} ??????T ret = items[head]; ??????items[head] = null ; ??????if(++head == getCapacity()){ ????????head =0 ; ??????} ??????--count; ??????notFull.signalAll(); ??????return ret ; ????} catch (InterruptedException e) { ??????e.printStackTrace(); ????}finally { ??????lock.unlock(); ????} ????return null ; ??} ? ??public int size(){ ????lock.lock(); ????try { ??????return count; ????}finally { ??????lock.unlock(); ????} ??} ? ??public static void main(String[] args){ ????MyArrayBlockingQueue<Integer> aQueue = new MyArrayBlockingQueue<>(); ????aQueue.put(3); ????aQueue.put(24); ????for(int i=0;i<5;i++){ ??????System.out.println(aQueue.take()); ????} ? ????System.out.println("結束"); ??} } |
執行結果:
3
24
還沒有數據,等待
三、信號量 Semaphore
Semaphore是一個計數信號量,它的本質是一個“共享鎖”。信號量維護了一個信號量許可集,線程可以通過調用acquire()來獲取信號量的許可。當信號量中有可用的許可時,線程能獲取該許可;否則線程必須等待,直到可用的許可為止。線程可以通過release()來釋放它所持有的信號量許可。
示例:
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class SemaphoreTest { ??public static void main(String[] args){ ????final ExecutorService executorService = Executors.newFixedThreadPool(3); ????final Semaphore semaphore = new Semaphore(3); ????List<Future> futures = new ArrayList<>(); ????for (int i = 0; i < 5; i++) { ??????Future<?> submit = executorService.submit(new Runnable() { ????????@Override ????????public void run() { ??????????try { ????????????semaphore.acquire(); ????????????System.out.println(" 剩余許可: " + semaphore.availablePermits()); ????????????Thread.sleep(3000); ????????????semaphore.release(); ??????????} catch (InterruptedException e) { ????????????e.printStackTrace(); ??????????} ????????} ??????}); ??????futures.add(submit); ????} ??} } |
以上就是本文的全部內容,希望對大家的學習有所幫助
總結
以上是生活随笔為你收集整理的Android多线程之同步锁的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从VC++到GCC移植:谈两者的语法差异
- 下一篇: Android Studio 使用Log