Java锁:
公平锁:从名词上来讲就是公平,大家排好队一个一个来,先到的先执行。
非公平锁:顾名思义就是,不公平竞争,多个线程来抢CPU资源,谁抢到谁执行。
Java的实现方式:ReentrantLock,使用带Boolean参数的构造方法,true表示公平锁,false表示非公平锁,如下图。
可重入锁:字面意思来看,就是加完锁以后还可以再加锁。Java中的ReentrantLock和synchronized也都实现了可重入锁。
读锁:又称为共享锁(S锁):一个事务对A加了S锁,其它事务只能对A加S锁,而不能加X锁,而且在释放锁之前不能对A进行任何修改。
写锁:又称为排它锁(X锁):一个事务对A加了X锁后,既能读取A又能修改A,其它事务不能对A进行加任何锁,直到当前的事务释放了X锁了,其它事务才能对A进行加锁。
synchronized和lock的区别
1、synchronized是个关键字,Lock是个接口。
2、synchronized发生异常或者程序执行完毕会自动释放锁,Lock不会需要手动释放锁(最好在finally中加解锁方法),否则出现死锁,别的线程无法加锁。
3、Lock可以响应中断,使用interrupt来中断,而synchronized不行,需要等待线程释放锁。
4、Lock可以通过trylock来知道有没有获取锁,而synchronized不能。
5、synchronized使用Object对象本身的wait 、notify、notifyAll调度机制,Lock可以使用Condition进行线程之间的调度。
6、性能上来说,如果线程竞争不激烈,两者性能差不多,如果竞争非常激烈时候,Lock性能远高于synchronized。
synchronized用法:
synchronized需要同步对象中加入此控制,synchronized可以加在方法上,也可以加在代码块中。
synchronized加在普通方法上,表示锁当前对象(例如hashtable,所有读写方法上都加了synchronized,多线程操作的情况下,虽然线程安全,但是只能有一个线程进行读写,性能非常低,是坨屎)。
synchronized加在静态方法上(static修饰的方法上),表示锁的是Class类,也就是锁当前类的字节码。
CAS操作:CAS的全称是compare and swap(比较和替换)原子性操作。
volatile关键字:变量修饰符,当一个线程进行修改后,其它线程立即可见,CPU在处理数据时候,为了提升效率会将内存数据读入CPU的寄存器中,如果一个线程对内存中的变量进行修改后,其它线程读取的只是CPU寄存器的数据。如果加了volatile关键字,一个线程修改后会刷新到主内存,其它线程立即可见。
CPU分为:ALU(计算器)、PC(程序计数器)、regesitery(寄存器)、cache(缓存)
操作系统进行线程调度
Java的线程和内核线程是1:1的关系
锁:
方法上加 synchronized 锁定的是this对象
static的方法上加synchronized,锁定的是字节码(Test.class)
自旋等待(自旋锁),轻量级锁,是不需要经过操作系统进行调度的
等待队列,需要经过操作系统调度(重量级锁)
自旋锁等待线程太多了,CPU都消耗在了自旋等待上
竞争特别激烈的时候,使用等待队列(重量级锁)
synchronized jdk1.0-1.2使用重量级锁,操作系统进行线程调度
jdk1.5以后juc并发包(java.util.concurrent包下的)
atomicinteger用的就是自旋锁,CAS(compareandswap比较并交换,原子性操作)实现方式就是自旋锁
CAS:自旋锁,不需要操作系统调度 也可以叫compare and set比较设置
ABA问题,加版本号解决
假如CAS修改值时候的原子性问题
偏向锁,不用抢,
有人竞争就锁升级升级为轻量级锁,当锁等待数超过一定数量,就升级为重量级锁
线程状态
new:尚未启动状态
runnable状态:可运行的线程状态,等待CPU调度
blocked:线程阻塞状态,等待监视器锁定的线程状态
处于synchronized同步代码块或方法或被阻塞
waiting:等待线程的线程状态,下列不带超时的方式:
Object.wait()、Thread.join()、LockSupport.park
Time Waiting:具有指定时间的等待线程的线程状态,带超时的方式:
Thread.sleep、Object.wait、Thread.join、LockSupport.parkNanos、LockSupport.parkUntil
Terminated: 终止线程的线程状态。线程正常完成执行或者出现异常
Thread.stop()不建议使用,会有线程安全问题,主线程调用stop()方法,可能线程还没有执行完,会有问题,正确使用终止线程的方法 interrupt()
线程中定义标志位 要用volotile修饰
(未完待续。。。。。。。。。。。。。。)