资讯专栏INFORMATION COLUMN

java的线程、锁相关

xavier / 994人阅读

摘要:那岂不是线程安全的对于普通同步方法,锁是当前实例对象。如果测试成功,表示线程已经获得了锁。然后线程尝试使用将对象头中的替换为指向锁记录的指针。

volatitle
这样的一行代码:

volatitle instance = new Singleton(); // instance是volatile变量

汇编后代码是这样子的

0x01a3de1d: movb $0×0,0×1104800(%esi);0x01a3de24: lock addl $0×0,(%esp);

当中有个lock指令,这个指令是做什么的呢?
1)将当前处理器缓存行的数据写回到系统内存。
2)这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效。

处理器不会直接跟内存打交道,而是缓存。所以,首先会将值写会内存,而后将该值的所有缓存设置为无效,包括多处理器环境下的缓存。(那岂不是线程安全的?)

synchronized
对于普通同步方法,锁是当前实例对象。
对于静态同步方法,锁是当前类的Class对象。
对于同步方法块,锁是Synchonized括号里配置的对象。

由于锁太重,为了提高syn会采取几种轻量级锁
1 偏向锁
HotSpot的作者发现,锁总是由同一个线程获得,因此当线程获得锁的时候,会在对象头和栈帧中的锁记录里存储锁偏向的线程ID,以后该线程在进入和退出同步块时不需要进行CAS操作来加锁和解锁,只需简单地测试一下对象头的Mark Word里是否存储着指向当前线程的偏向锁。如果测试成功,表示线程已经获得了锁。

如果测试失败,则需要再测试一下Mark Word中偏向锁的标识是否设置成1(表示当前是偏向锁):如果没有设置,则使用CAS竞争锁;如果设置了,则尝试使用CAS将对象头的偏向锁指向当前线程

2 轻量级锁
线程在执行同步块之前,JVM会先在当前线程的栈桢中创建用于存储锁记录的空间,并
将对象头中的Mark Word复制到锁记录中,官方称为Displaced Mark Word。然后线程尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针。如果成功,当前线程获得锁,如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁

单例模式可能的问题
double check可能会存在问题

public class Singleton{
     private static Singleton instance = null;
     private Singleton(){}

     public static Singleton getInstance(){
            if(instance == null){
                   synchronized(Singleton.class){
                        if(instance == null)
                        instance = new Singleton();//问题
                   }           
             }
            return instance;
    }
}

在问题步骤中,对象的创建包含了三个环节
1 分配空间
2 栈指针指向空间
3 实例化对象

但由于jvm的指令重排序,可能1->3->2
那么如果一个线程执行完1->3 跳出了syn块
那么第二个线程判断实例非空,直接返回,但事实上并没有初始化掉,因此存在问题

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69979.html

相关文章

  • 并发学习笔记(2)

    摘要:当其他线程调用时,它们被阻塞,直到第一个线程释放锁对象。包关于获取这个锁如果锁同时被另一个线程拥有则发生阻塞。所以必须确保没有其他线程再检查余额和转账活动之间修改金额。方法添加一个线程到等待集中,方法解除等待线程的阻塞状态。 避免代码块受到并发访问的干扰 java语言提供了两种机制实现这种功能 Synchonized 关键字(调用对象内部的锁) synchronized关键字自动...

    saucxs 评论0 收藏0
  • java线程相关

    摘要:那岂不是线程安全的对于普通同步方法,锁是当前实例对象。如果测试成功,表示线程已经获得了锁。然后线程尝试使用将对象头中的替换为指向锁记录的指针。 volatitle这样的一行代码: volatitle instance = new Singleton(); // instance是volatile变量 汇编后代码是这样子的 0x01a3de1d: movb $0×0,0×1104800...

    VPointer 评论0 收藏0
  • Java 重入 ReentrantLock 原理分析

    摘要:的主要功能和关键字一致,均是用于多线程的同步。而仅支持通过查询当前线程是否持有锁。由于和使用的是同一把可重入锁,所以线程可以进入方法,并再次获得锁,而不会被阻塞住。公平与非公平公平与非公平指的是线程获取锁的方式。 1.简介 可重入锁ReentrantLock自 JDK 1.5 被引入,功能上与synchronized关键字类似。所谓的可重入是指,线程可对同一把锁进行重复加锁,而不会被阻...

    lx1036 评论0 收藏0
  • 浅谈Java并发编程系列(七) —— 深入解析synchronized关键字

    摘要:第一个字被称为。经量级锁的加锁过程当一个对象被锁定时,被复制到当前尝试获取锁的线程的线程栈的锁记录空间被复制的官方称为。根据锁对象目前是否处于被锁定状态,撤销偏向后恢复到未锁定或经量级锁定状态。 Synchronized关键字 synchronized的锁机制的主要优势是Java语言内置的锁机制,因此,JVM可以自由的优化而不影响已存在的代码。 任何对象都拥有对象头这一数据结构来支持锁...

    piglei 评论0 收藏0
  • 手撕面试官系列(七):面试必备之常问并发编程高级面试专题

    摘要:如何在线程池中提交线程内存模型相关问题什么是的内存模型,中各个线程是怎么彼此看到对方的变量的请谈谈有什么特点,为什么它能保证变量对所有线程的可见性既然能够保证线程间的变量可见性,是不是就意味着基于变量的运算就是并发安全的请对比下对比的异同。 并发编程高级面试面试题 showImg(https://upload-images.jianshu.io/upload_images/133416...

    Charles 评论0 收藏0

发表评论

0条评论

xavier

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<