synchronize、ReentrantLook及AQS理解

在jdk1.6之前
如果要挂起或者唤醒一个线程,都需要操作系统帮忙来完成,而操作系统实现线程之间的切换时需要用户转换到内核态,
这个状态之间的转换需要相对比较长的时间,时间成本太高,这也是早期synchronize效率低的原因。

jdk 1.6之后
引入了大量的优化,如自旋锁、偏向锁等等

1.当修饰同步语句的时候
monitor enter
monitor exit
当锁计数器为0的时候抢占锁。为1的时候线程阻塞等待。
2.当修饰方法的时候
synchronize修饰的方法没有monitor,取而代之的是ACC_SYNCHRONIZED标示指明该方法是一个同步方法,JVM通过ACC_SYNCHRONIZED
访问标示来辨别一个方法是否声明同步方法。

锁的主要的四种状态:无锁、偏向锁、轻量级锁、重量级锁状态。只可以升级但是不可以降级,为了提高锁的释放效率。

synchronize依赖于JVM 而ReenTranLook是JDK层面的。需look.look()、UNlook;
ReenTranLook比synchronize增加了一些高级功能
1.等待可中断
2.可实现公平锁
3.可实现选择性通知(锁可以绑定多个条件)线程对象可以注册在指定的condition中,从而有选择性的进行线程通知。

synchronize关键字和volatile关键字的区别
volatile是线程同步的轻量级实现,所以volatile的性能比synchronize关键字要好。
volatile但只能用于变量而不能修饰方法和代码块

为什么要用线程池
1.降低资源消耗(通过重复利用已创建的线程降低线程创建和销毁的消耗)
2.提高响应速率(当任务到达时,任务可以不需要的等到线程创建就能立即执行)
3.提高线程的可管理性(线程是稀有资源,如果无线创建。不仅会消耗系统资源,还会降低系统稳定性)

创建线程池
为了明确线程池的运行规则一般使用ThreadPollExecutor创建线程

AQS原理
AQS是一个用来构建锁和同步器的框架,使用AQS能简单且高效地构造出广泛的大量的同步器。

AQS核心思想:
如果被请求的共享资源空间空闲,则将当前请求资源的线程设置为有效的工作线程,并将共享资源设置为锁的状态。
如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配机制,这个机制AQS用的CLH队列锁,将暂时获取不到锁的线程加入到队列。

AQS使用CAS对同步状态进行原子性操作

AQS两种资源共享方式
Exclusive(独占):只有一个线程能执行,ReentrantLook。
Share(共享):多个线程可以同时执行Semaphore

你可能感兴趣的:(synchronize、ReentrantLook及AQS理解)