Android多线程之同步锁的使用
本文主要介绍了Android多线程之同步锁的使用,分享给大家,具体如下:
一、同步机制关键字synchronized
对于Java来说,最常用的同步机制就是synchronized关键字,他是一种基于语言的粗略锁,能够作用于对象、函数、class。每个对象都只有一个锁,谁能够拿到这个锁谁就有访问权限。当synchronized作用于函数时,实际上锁的也是对象,锁定的对象就是该函数所在类的对象。而synchronized作用于class时则是锁的这个Class类,并非具体对象。
publicclassSynchronizedClass{ publicsynchronizedvoidsyncMethod(){ //代码 } publicvoidsyncThis(){ synchronized(this){ //代码 } } publicvoidsyncClassMethod(){ synchronized(SynchronizedClass.class){ //代码 } } publicsynchronizedstaticvoidsyncStaticMethod(){ //代码 } }
上面演示了同步方法、同步块、同步class对象、同步静态方法。前2种锁的是对象,而后两种锁的是class对象。对于class对象来说,它的作用是防止多个线程同时访问添加了synchronized锁的代码块,而synchronized作用于引用对象是防止其他线程访问同一个对象中synchronized代码块或者函数。
二、显示锁———-ReentrankLock和Condition
ReentrankLock和内置锁synchronized相比,实现了相同的语义,但是更具有更高的灵活性。
(1)获得和释放的灵活性。
(2)轮训锁和定时锁。
(3)公平性。
基本操作:
lock():获取锁
tryLock():尝试获取锁
tryLock(longtimeout,TimeUnitunit):尝试获取锁,如果到了指定的时间还获取不到,那么超时。
unlock():释放锁
newCondition():获取锁的Condition
使用ReentrantLock的一般组合是lock、tryLock、与unLock成对出现,需要注意的是,千万不要忘记调用unlock来释放锁,负责可能引发死锁的问题。ReentrantLock的常用形式如下所示:
publicclassReentrantLockDemo{ Locklock=newReentrantLock(); publicvoiddoSth(){ lock.lock(); try{ //执行某些操作 }finally{ lock.unlock(); } } }
需要注意的是,lock必须在finally开中释放,否则,如果受保护的代码抛出异常,锁就可能永远得不到释放!!
ReentrantLock类中还有一个重要的函数newCondition(),该函数用户获取Lock()上的一个条件,也就是说Condition与Lock绑定。Condition用于实现线程间的通信,他是为了解决Object.wait(),nofity(),nofityAll()难以使用的问题。
Condition的方法如下:
await():线程等待
await(inttime,TimeUnitunit)线程等待特定的时间,超过的时间则为超时。
signal()随机唤醒某个等待线程
signal()唤醒所有等待中的线程
示例代码:
publicclassMyArrayBlockingQueue{ //数据数组 privatefinalT[]items; privatefinalLocklock=newReentrantLock(); privateConditionnotFull=lock.newCondition(); privateConditionnotEmpty=lock.newCondition(); //头部索引 privateinthead; //尾部索引 privateinttail; //数据的个数 privateintcount; publicMyArrayBlockingQueue(intmaxSize){ items=(T[])newObject[maxSize]; } publicMyArrayBlockingQueue(){ this(10); } publicvoidput(Tt){ lock.lock(); try{ while(count==getCapacity()){ System.out.println("数据已满,等待"); notFull.await(); } items[tail]=t; if(++tail==getCapacity()){ tail=0; } ++count; notEmpty.signalAll();//唤醒等待数据的线程 }catch(InterruptedExceptione){ e.printStackTrace(); }finally{ lock.unlock(); } } publicintgetCapacity(){ returnitems.length; } publicTtake(){ lock.lock(); try{ while(count==0){ System.out.println("还没有数据,等待"); //哪个线程调用await()则阻塞哪个线程 notEmpty.await(); } Tret=items[head]; items[head]=null; if(++head==getCapacity()){ head=0; } --count; notFull.signalAll(); returnret; }catch(InterruptedExceptione){ e.printStackTrace(); }finally{ lock.unlock(); } returnnull; } publicintsize(){ lock.lock(); try{ returncount; }finally{ lock.unlock(); } } publicstaticvoidmain(String[]args){ MyArrayBlockingQueue aQueue=newMyArrayBlockingQueue<>(); aQueue.put(3); aQueue.put(24); for(inti=0;i<5;i++){ System.out.println(aQueue.take()); } System.out.println("结束"); } }
执行结果:
3
24
还没有数据,等待
三、信号量Semaphore
Semaphore是一个计数信号量,它的本质是一个“共享锁”。信号量维护了一个信号量许可集,线程可以通过调用acquire()来获取信号量的许可。当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到可用的许可为止。线程可以通过release()来释放它所持有的信号量许可。
示例:
publicclassSemaphoreTest{ publicstaticvoidmain(String[]args){ finalExecutorServiceexecutorService=Executors.newFixedThreadPool(3); finalSemaphoresemaphore=newSemaphore(3); Listfutures=newArrayList<>(); for(inti=0;i<5;i++){ Future>submit=executorService.submit(newRunnable(){ @Override publicvoidrun(){ try{ semaphore.acquire(); System.out.println("剩余许可:"+semaphore.availablePermits()); Thread.sleep(3000); semaphore.release(); }catch(InterruptedExceptione){ e.printStackTrace(); } } }); futures.add(submit); } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。