Android多线程 同步锁 - muyu01248/usb GitHub Wiki
http://blog.csdn.net/a992036795/article/details/51372272 一、同步机制关键字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 {
// 数据数组 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 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); } } }