美文网首页
java与锁

java与锁

作者: 靈08_1024 | 来源:发表于2018-05-26 09:16 被阅读6次

    本篇源自于本人以前的《JAVA安全与并发》一文。因其文太长,所以剔出。

    synchronized

    synchronized是依赖于JVM来执行锁的。属于公平锁。悲观锁。
    使用范围:代码块,方法,静态方法,类。
    特性:不可中断,可读性好。
    场景:不激烈的竞争场景,线程少。
    实现:JVM实现。

    ReentrantLock

    ReentrantLock依赖于JDK来实现的。循环调用CAS来实现操作。
    默认为非公平锁(可配)。乐观锁(只有在用到值时才进行CAS判断比较)。
    特性:可中断,多样化同步。
    场景:激烈的竞争场景,线程多。
    实现:CAS+volatile的int。

    ReentrantReadWriteLock

    在没有任何读写锁时,才可以取得写入锁。其写入锁时悲观锁。读时乐观锁。
    特性:两把锁。
    场景:一般用于两个地方对相同多变量的修改和读取。
    实现:CAS+volatile的int,基于高低16位来区分读或写。

    *atomic和volatile不是锁,但在某些情况下,有着比锁更好或者更方便的使用

    atomic

    特性:比lock性能还好。但每次只能更新一个值。不属于锁,但和锁一样有原子性的功能。
    场景:不激烈的竞争场景。
    实现:基于CPU的CAS。

    volatile

    因为JVM对于代码会进行指令重排序,所以volatile出现了。volatile通过实现内存屏障禁止重排序来实现的。不属于锁,但在部分场景中有同步的效果,且比锁性能好很多。
    对于volatile的变量,在每次读之前会从主内存中load,在每次更新后会store到主内存中。
    volatile不具有原子性。
    volatile的使用需要满足:1.对变量的操作不依赖于当前值;2.该变量没有包含在具有其他变量不变的表达式中。
    适用场景:1.作为状态标记量,2.双重检查。
    实现:读写屏障。读屏障:loadload-读操作-loadstore;写屏障:storestore-写操作-storeload。

    多线程共享变量不可见的原因:

    1. 线程交叉执行;
    2. 重排序结合线程交叉执行;
    3. 共享变量更新后,没有在工作内存和主内存中进行及时更新。
    可重入性 锁的实现依赖 性能 便利性 灵活性 锁类型 唤醒机制 是否可以中断
    ReentrantLock 依赖于JDK - 公平锁和非公平锁 支持部分唤醒
    synchronized 依赖于JVM - 公平锁 唤醒一个或者全部

    公平锁:每个线程抢占锁的顺序为先后调用lock方法的顺序依次获取锁,类似于排队吃饭。
    非公平锁:每个线程抢占锁的顺序不定,谁运气好,谁就获取到锁,和调用lock方法的先后顺序无关,类似于堵车时,加塞的那些XXXX。

    死锁

    死锁的原因
    • 系统资源不足;
    • 进程运行推进的顺序不合适;
    • 资源分配不当。
    死锁的必然条件

    出现死锁后,肯定会出现下面的现象:

    • 互斥条件:一个资源每次只能被一个线程使用。
    • 请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源不释放。
    • 不剥夺条件:线程已获得的资源,在末使用完之前,不能强行剥夺。
    • 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。

    相关文章

      网友评论

          本文标题:java与锁

          本文链接:https://www.haomeiwen.com/subject/zjiujftx.html