1.线程:一个程序(动态称作进程)不同的执行路径
2.创建线程的两种方式:实现thread类,实现runable接口,
3.线程方法:sleep休眠一定时间后自动复活;yield当前线程调用时,先退出一下,进入一个等待队列,让出一下cpu,工程中很少遇到;join,t1线程调用另一个线程t2的join方法,将t2加入t1的执行过程,t2执行完成后才继续运行t1;stop方法不要用;inter
4.java线程状态:六个状态:new,还未调用start方法;runable,调用了start,就绪状态,扔到cpu的等待队列里ready;running,yield调用的时候线程会从running状态切换为ready状态,线程被调度器选中执行的时候又从ready状态切换为running状态;teminated状态,线程执行完成后是teminated状态,不可再次被start;runable状态中,可有waiting,timewaiting,blocking集中状态的变化,加上同步代码块的时候,会blocking;
5.synchronized,获取到锁之后才能执行同步块的代码,hotspot将对象头的两位标志位来设定对象的锁。锁定是锁的对象,而不是代码。synchronized方法和synchronized(this)是等效的,静态方法加synchronized锁的是当前对象所属类的class对象。
6.synchronized即保证了原子性,又保证了可见性
7.银行账户的余额读方法,是否加锁取决于业务逻辑是否允许脏读
8.synchronized可重入属性:一个同步方法加了锁,调用另一个加同一把锁的同步方法,可以互相调用,如果不允许可重入,则会发生死锁现象,也就是允许同一个线程再次获取同一把锁。还有一种例子,就是父类里有方法m1是同步加锁的,子类重写了该方法,且子类里调用了super(),如果不可重入,也是死锁。重入锁,加一把锁,锁++,减一把锁就锁--
9.父类里有synchronized(this),那么子类调用父类的这个方法,this是指子类,因为jvm运行时绑定,方法里有this参数,方法执行到谁,this就传的谁
10.如果出现异常,锁会被释放,会让等待队列的其他线程抢夺到锁
11.早期的synchronized是重量级的,需要申请os内核态的锁,性能很低;后期做了改进,hotspot做了锁升级,synchronized(this)刚进来的时候,在this的Markword的头上记录一下当前线程的id,这是偏向锁,默认不会有其他线程抢锁,效率非常高,如果还是这个线程再次进来,验证是否是之前线程,如果有线程争用,就升级为自旋锁,用while(true)循环为等待,十次以后,如果还得不到这把锁,升级为重量级锁,就是去os内核态申请锁。锁只能升级,不能降级。
偏向锁:先不加锁,先记录初次线程的id值,认为这个对象锁时这个线程独有,下次此线程再来的时候,判断是否那个线程,如果是就不需要加锁,还是可以执行,如果下次来的线程是新的线程,则首先升级为自旋锁,那么其他线程就在自旋等待,转圈(占用cpu资源),10次以后升级为重量级锁
12.atomic相当于自旋锁,用户态解决锁的问题,占用cpu,不经过内核态,如果线程执行时间短,用自旋锁,并且此时等待队列不能太多,因为太多了其他线程自旋的时候会占用大量cpu资源;如果线程执行时间长(其他线程自旋时间比较长),等待队列比较多的情况下(多个线程在自旋,很耗费cpu资源),用synchronized系统锁。