更新时间:2017年8月15日11:43:02 作者:blueberry_mu
本文主要介绍Android多线程同步锁的使用。 小编感觉还不错。 现在就分享给大家,给大家一个参考。下面就跟随小编一起来看看吧。
本文主要介绍Android多线程同步锁的使用,分享给大家,如下:
1.同步机制关键字synchronized
对于Java来说,最常用的同步机制是synchronized关键字,它是一种简单的基于语言的锁,也可以应用于对象、函数和类。 每个对象只有一把锁,谁能拿到锁,谁就拥有访问权。 Synchronized作用于函数时,实际上是对该对象进行了锁定,而锁定的对象是该函数所在类的对象。 Synchronized作用于类时,是锁的Class类,而不是具体的对象。
public class SynchronizedClass { public synchronized void syncMethod(){ //代码 } public void syncThis(){ synchronized (this){ //代码 } } public void syncClassMethod(){ synchronized (SynchronizedClass.class){ //代码 } } public synchronized static void syncStaticMethod(){ //代码 } }
它演示了同步方法、同步块、同步类对象和同步静态方法。 前两个锁是对象,而后两个锁是类对象。 对于类对象来说,它的作用是防止多个线程同时访问加了synchronized锁的代码块,而synchronized作用于引用对象typescript同步锁,防止其他线程访问同一个对象中的synchronized代码块或函数。
2.显示锁————ReentrankLock和Condition
与外部锁synchronized相比,ReentrankLock实现了相同的语义,并且具有更高的灵活性。
(1)获取和释放的灵活性。
(2)旋转锁和定时锁。
(3)公平。
基本操作:
lock():获取锁
tryLock():尝试获取锁
tryLock(longtimeout,TimeUnitunit):尝试获取锁。 如果在规定的时间内无法获取到,就会超时。
unlock():释放锁
newCondition():获取锁的Condition
通常使用ReentrantLock的组合是lock、tryLock、unLock成对出现。 需要注意的是,不要忘记调用unlock来释放锁,这就是造成可能导致死锁的问题的原因。 ReentrantLock的常用方法如下:
public class ReentrantLockDemo { Lock lock = new ReentrantLock(); public void doSth(){ lock.lock(); try { //执行某些操作 }finally { lock.unlock(); } } }
需要注意的是typescript同步锁,finally打开时必须释放锁,否则,如果受保护的代码抛出异常,锁可能永远不会被释放! !
ReentrantLock类中还有一个重要的函数newCondition(),它允许用户获取Lock()上的一个条件,也就是说,Condition与Lock绑定。 Condition用于实现线程之间的通信。 就是为了解决Object.wait()、nofity()、nofityAll()不能使用的问题。
条件如下:
wait():线程等待
wait(inttime,TimeUnitunit) 线程等待特定时间,超过时间即超时。
signal() 随机唤醒一个等待线程
signal() 调用所有等待线程
示例代码:
public class MyArrayBlockingQueue { // 数据数组 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 aQueue = new MyArrayBlockingQueue(); aQueue.put(3); aQueue.put(24); for(int i=0;i<5;i++){ System.out.println(aQueue.take()); } System.out.println("结束"); } }
结果:
24
暂无数据,等待
3. 信号量
信号量是一种计数信号量,本质上是一个“共享锁”。 信号量维护一个信号量权限集,线程可以通过调用acquire()来获取信号量权限。 当信号量中有权限时,线程可以获得该权限; 否则线程必须等待,直到有可用的权限。 线程可以通过release()释放它所持有的信号量权限。
例子:
public class SemaphoreTest { public static void main(String[] args){ final ExecutorService executorService = Executors.newFixedThreadPool(3); final Semaphore semaphore = new Semaphore(3); List 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); } } }
以上就是本文的全部内容。 希望对您的学习有所帮助,也希望您多多支持脚本之家。