首页 > 系统 > Android > 正文

Android多线程之同步锁的使用

2019-12-12 02:15:09
字体:
来源:转载
供稿:网友

本文主要介绍了Android多线程之同步锁的使用,分享给大家,具体如下:

一、同步机制关键字synchronized

对于Java来说,最常用的同步机制就是synchronized关键字,他是一种基于语言的粗略锁,能够作用于对象、函数、class。每个对象都只有一个锁,谁能够拿到这个锁谁就有访问权限。当synchronized作用于函数时,实际上锁的也是对象,锁定的对象就是该函数所在类的对象。而synchronized作用于class时则是锁的这个Class类,并非具体对象。

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的常用形式如下所示:

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() 唤醒所有等待中的线程

示例代码:

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()来释放它所持有的信号量许可。

示例:

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);    }  }}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表