美文网首页
[笔记]Java中的锁相关知识

[笔记]Java中的锁相关知识

作者: 蓝灰_q | 来源:发表于2017-10-10 22:18 被阅读23次

    原子性、可见性、有序性

    原子性:一段指令不会被拆分给多个处理器执行
    synchronized能实现原子性
    可见性:数据被修改后,其他线程立即得知这个变化
    volatile、synchronized和final都能实现可见性
    有序性:编译器处理字节码时,会做重排序,避免重排序就是有序性
    volatile、synchronized能实现有序性

    Synchronized

    实例对象/方法锁
    synchronized一般就是锁一个代码块或锁一个方法:
    锁代码块synchronized(this) //当前类实例对象
    锁方法public synchronized void test(){}
    在实例锁中,其实锁的对象都是类的实例对象
    类锁(静态类/方法锁)
    与实例对象/方法锁的区别在于,静态类和静态方法,都是在方法区的唯一内存,相应的锁也是唯一的。
    实例对象锁和类锁是两个不同的锁,互不干扰,甚至可以同时获取。
    内置锁
    每个java对象可以作为一个锁,也就是内置锁,这样在同步时不需要显式的创建锁对象
    所以,synchronized只是个内置锁的加锁机制,某个方法加上了synchronized后,线程就必须获取内置锁后才能执行,同时,其他线程,可以访问未加锁的对象和方法。
    对代码块加锁的优势
    synchronized同步会阻塞其他线程,这是性能上的巨大损耗,对方法加锁的话,锁对象就是实例对象,不可优化。
    但是对代码块加锁的话,一方面可以尽早释放锁;另一方面可以传不同的锁对象,
    java synchronized关键字的用法

    Lock(和ReentrantLock)

    synchronized其实是jvm提供的同步机制,而lock是依赖硬件cpu指令实现的。
    所以,用lock实现同步,需要自己实现复杂的代码,lock、unlock成对出现,并确保在finally中unlock。
    另外,synchronized是悲观锁,必须阻塞其他线程;而lock可以实现乐观锁,不阻塞,失败重试,消耗低。
    可重入锁Reentrantlock是lock的一个子类,有三处改进:可以锁多个对象、可以主动退出等待、可以按请求的先后顺序分配锁。

    Volatile

    每个工作线程都有自己的工作内存,工作内存的数据来自于主内存,并写回到主内存。
    Volatile是易变的,它的机制就是对数据的修改立即写回主内存,在使用数据时再立即从主内存取一次数据(因为是易变的),实际就是依靠主内存来实现可见性。
    不过,volatile在运算时数据仍然可能不是最新的,因为一行java代码,最终形成的机器码可能有多行,在前面拿到的volatile数据,在后面真正操作时,可能已经不是最新的了。

    Final

    只在类的加载连接阶段写一次,然后不再修改,所以满足可见性,就是说,它通过不修改满足了修改结果可见。

    sleep和wait/notify

    sleep仍持有锁,wait释放了锁,要等别的线程notify通知才能去尝试拿回锁

    相关文章

      网友评论

          本文标题:[笔记]Java中的锁相关知识

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