看完后,你再也不用怕面试问并发编程啦( 九 )

 小结

  • 哪些对象可以作为锁?
任意对象 。
  • synchronized锁对象时候要注意什么?
多线程并发方法同步代码块,需要锁同一个对象 。
  • synchronized中的锁的作用是什么?
同步代码块中有锁的线程进入,无锁的线程需要等待 。
synchronized 同步方法
synchronized 同步方法解决线程安全问题
语法// 普通同步方法,对当前一个实例对象加锁 , 多线程操作同一个对象实例进行同步操作public synchronized void 方法名() { ...}// 静态同步方法,对类加锁,多线程操作当前类所有实例对象进行同步操作public static synchronized void 方法名() { ...} 代码:package cn.itcast.thread;/** 学习使用同步代码块解决线程安全问题 */public class Test9 { // 定义票的总数量 private static int ticket = 100; public static void main(String[] args) { Runnable runnable = () ->{ // 循环买票 while (true){ try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } sell(); } }; // 创建3个线程 Thread t1 = new Thread(runnable, "窗口1"); Thread t2 = new Thread(runnable, "窗口2"); Thread t3 = new Thread(runnable, "窗口3"); t1.start(); t2.start(); t3.start(); } // 同步方法 private static synchronized void sell() { // 同步代码块(类锁) if (ticket > 0) { ticket--; System.out.println(Thread.currentThread().getName() + "卖了一张票,剩余:" + ticket); } }} 小结
synchronized是通过对象内部的一个叫==监视器锁==来实现的,但是监视器锁本质又是依赖底层的操作系统的Mutex(互斥) Lock来实现的,而操系统实现线程之间的切换会造成带量的CPU资源浪费,这个成本非常的高,状态之间的转换需要相对比较长的时间 , 这就是为什么Synchronized效率低的原因,因此这种依赖于操作系统Mutex Lock所实现的锁我们称之为:==重量级锁== 。JDK中对Synchronized做的种种优化,其核心都是为了减少这种重量级锁的使用,JDK1.5以后,为来减少获得锁和释放锁所带来的性能消耗, JDK引入了:”轻量级锁“和”偏向锁“进行优化,这个优化自动的无需开发人员介入 。
synchronized 属于最基本的线程通信机制,基于对象监视器实现的 。Java中的每个对象都与一个监视器相关联,一个线程可以锁定或解锁 。一次只有一个线程可以锁定监视器 。试图锁定该监视器的任何其他线程都会被阻塞,直到它们可以获得该监视器上的锁定为止 。12、Java中的锁:ReentrantLock目标:学习使用ReentrantLock可重入锁解决线程安全问题
介绍
  • synchronized 是内部锁,自动化的上锁与释放锁,而lock是手动的,需要人为的上锁和释放锁,lock比较灵活 , 但是代码相对较多
  • lock接口异常的时候不会自动的释放锁,同样需要手动的释放锁,所以一般写在finally语句块中,而synchronized则会在异常的时候自动的释放锁
API方法
  • lock()
用来获取锁,如果锁被其他线程获?。?处于等待状态 。如果采用Lock,必须主动去释放锁,并且在发生异常的时候 , 不会自动释放锁 。因此一般来说,使用Lock必须早try{}catch{}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被释放,防止死锁发生 。
  • lockInterruptibly()
通过这个这个方法去获取锁时,如果线程正在等待获取锁 , 则这个线程能够响应中断,即中断线程的等待状态 。
  • tryLock()
tryLock方法是有返回值的,它表示用来尝试获取锁,如果获取成功 , 则返回true,如果获取失败(即锁已经由其他线程获取),则返回false,也就是说这个方法无论如何都会立即返回 。在获取不到锁的时候,不会再那一直等待 。
  • tryLock(long time, TimeUnit unit)
与tryLock类似,只不过是有等待时间,在等待时间内获取到锁返回true,超时返回false 。
  • unlock()
释放锁,一定要在finally块中释放 。
Lock锁使用语法
Lock介绍:  
  • 比synchronized更灵活,可以自己调用方法    
  • void lock() 获得锁    
  • void unlock() 释放锁
Lock实现类:  


推荐阅读