线程的状态

    线程的stop方法太粗暴,不允许使用,应该让线程正常执行完成

synchronized

    锁本身🔒的不是代码,而是对象(使用锁时不要使用String,Integer,Long等基础数据类型和包装类型,可能会锁住其他使用到相同常亮指向的对象)
    锁加上static上锁的是this对象
    同步方法和非同步方法是可以同时执行的,且synchronized是可重入锁
    synchronized是无法阻止重排序的,volatile才会保证重排序

synchronized的🔒锁升级 无锁->偏向->自旋->重量级

synchronized的🔒锁优化

1.锁细化
    写编写业务代码需要使用到synchronized时
    应该要考虑到应该加锁的代码块,锁住的代码越少越好,锁住会出现多线程问题的代码即可
    锁的粒度越细,线程锁争用的时间会很短,从而提升效率
2.锁粗化
    如果一段程序代码中使用到了很多的小锁,锁的粒度虽然很细,但是锁的点很多,这样造成的锁争用反而会更大
    此时线程频繁的争用细粒度的锁,不如直接锁粗化,将一长段小锁变成一个大锁,这样会降低锁争用的次数,从而提高效率
注意点
    在使用某个对象当锁时,如果这个对象发生了改变,程序则会出错
    因为锁的信息是放在对象的头2位,如果在运行期间改变了这个对象,则这个对象的头信息也会发生变化
    则这个锁的信息发生了不可预估的走向,所以在用某个指定对象当锁时,一定要加上final使其无法改变.
    一定不要用string等基础类型当锁
    代码不是万能的final也可以通过反射改变,class也可以被asm改,二进制也可以被改写,但是没必要考虑,否则代码写不下去了

Lock

    synchronized的锁是非公平的,谁先抢到就是谁的
    Lock锁在相较于synchronized有自己的优势
    ReentrantLock提供了公平锁与非公平的切换(相对公平)
    lock有trylock可以尝试锁定,如果无法锁定可以执行后续的对应代码
    lockinterupptibly打断方法

MarriagePhaser(扩展,几乎无使用)

    栅栏,重写onAdvance方法可以控制流程
    arriveAndAwaitAdvance();用来加入当前流程中
    arriveAndDeregister();当前现场退出
    register();将当前线程注册到当前流程中

ReadWritelock(读是共享锁,写是排他锁/互斥锁)

    读的时候不能写,写的时候不能读
    如果是读的线程访问,加上读锁,其他读线程可以同时进行(共享锁)
    如果是写操作就会上写锁定,挨个执行,写操作只有执行完成后续的线程才能走(排他锁)

semaphore

    可以做限流锁,也有公平方法
    如果线程要继续执行只有在acquire得到锁后才可以执行


分布式锁(redis,zookeeper,mysql都可以实现)

文档更新时间: 2020-11-05 16:55   作者:mlrs