java线程(三)syschronized同步原理

本文详细介绍了Java中`synchronized`关键字的同步原理,包括保证原子性、可见性和有序性。讲解了synchronized的用法,如修饰静态方法、实例方法和同步代码块,并探讨了其在JDK1.6后的优化,如偏向锁、轻量锁和重量锁。此外,还分析了锁的状态转换、Monitor结构以及加锁和释放锁的字节码层面原理。
摘要由CSDN通过智能技术生成

作用

  • 保证原子性(同步代码中的执行不受其他线程干扰),可见性(同步代码中修改后的数据,退出同步后,对其他线程立即可见),有序性(多条线程有序执行)

用法

  • 修饰静态方法,相当于对类的class对象加锁。
  • 修饰实例方法,相当于对当前实例对象加锁。
  • 同步代码块,可以自由选定加锁对象。

知识点

  • jdk1.6之前单纯通过monitor实现锁,但因为需要切换内核态执行线程阻塞和线程唤醒等调用系统函数,性能比较差。jdk1.6之后做了优化,锁分为偏向锁、轻量锁、重量锁,底层根据不同的锁状态实现不同的同步机制,其中重量锁即通过monitor实现。1.6之后与reentrantlock性能差不多,synchronized使用相对比较简单,但是synchronized只支持非公平锁,且等锁不可中断。
  • 非公平锁。没有先来后到,线程相互竞争,依赖系统调度。非公平锁可能会出现饥饿问题,低优先级的线程一直在阻塞等锁,得不到cpu执行机会,获得锁的线程一直占用锁,或者是wait之后一直没有被唤醒。解决饥饿问题可以用公平锁
  • 获取锁的阻塞状态不可中断,因此出现死锁不可中断。

对象组成

  • 实例数据。存储类的属性数据,包括父类的数据。
  • 填充数据。虚拟机要求对象的起始地址必须是8字节的整数倍,如果对象实例数据不是8字节的整数倍,则会自动填充数据补全。
  • 对象头。分为三个部分,mark word存储对象的hashcode、是否是偏向锁、锁标记位、分代年龄等(如果是偏向锁,还会包含一个偏向的线程id,重量级锁包含指向monitor的指针)。klass 指向对象的类信息的指针(当类被加载的时候,jvm会为该类创建instantKlass对象存储在方法区)。如果是数组类型,还会存储数组长度。
  • 当对象锁的状态是偏向锁时,mark word存储的是偏向的线程id。当对象的状态是轻量锁时,mark word存储的是线程栈中的lock record指针。当对象锁的状态是重量级锁时,存的是指向堆中的monitor对象指针。

monitor

  • monitor是一种程序结构,synchronized基于monitor对象实现同步,每个对象的对象头包含一个指针指向monitor对象,通过一系列机制实现多线程互斥访问共享资源。

HotSpot中monitor结构中的几个主要属性

  • head  存储锁对象的mark word
  • count  记录线程获取锁的次数
  • waiters  处于wait状态的线程数
  • waiterSet  获得锁后进入wait状态的线程集合。
  • recursions  重入次数
  • cxq  竞争队列、所有请求锁的线程都会进入此队列,单向链表结构。
  • EntryList  等待获取锁的线程集合。cxq中的线程获取竞争锁的资格时,会进入此队列。
  • object  指向该monitor的锁对象
  • owner  获取monitor的线程

ObjectWaiter 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值