欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android多线程之同步锁的使用

程序员文章站 2023-11-26 18:18:28
本文主要介绍了android多线程之同步锁的使用,分享给大家,具体如下: 一、同步机制关键字synchronized 对于java来说,最常用的同步机制就是syn...

本文主要介绍了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);
    }
  }
}

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