如何理解java中锁与并发

发布时间:2021-09-27 09:52:13 作者:柒染
来源:亿速云 阅读:108

本篇文章为大家展示了如何理解java中锁与并发,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

1. 对象头和锁

1.1 对象头的概念

在java虚拟机的实现中,每个对象都有一个对象头,用于保存对象的系统信息。对象头中有一个称为Mark Word的部分,它是实现锁的关键。在32位系统中,Mark Word 为一个32位的数据,在64位系统中,它占64位。它是一个多功能的数据区,可以存放对象的哈希值、对象年龄、锁的指针等信息。一个对象是否占用锁、占用哪个锁,就记录在这个Mark Word中。

以32位系统为例,普通对象的对象头如下:

hash: 25 --------->| age: 4    biased_lock: 1    lock: 2

它表示Mark Word 中有25位表示对象的哈希值,4位表示对象的年龄,1位表示是否为偏向锁,2位表示锁的信息。

1.2 偏向锁的对象头

偏向锁是jdk 1.6提出的一种锁优化方式。其核心思想是,如果程序没有竞争,则取消之前已经取得锁的线程同步操作。也就是说,某一锁被线程获取后,就会进入俯身模式,当线程再次请求这个锁时,无须再进行相关的同步操作,从而节省了操作时间。如果在此期间有其他线程进行了锁请求,则锁退出偏向模式。在jvm中,使用-XX:+UseBiasedLocking可以设置启用偏向锁。

对于偏向锁的对象,它的格式如下:

[JavaThread*  | epoch | age | 1 | 01]

前23位表示持有偏向锁的线程,后续2位表示偏向锁的时间戳(epoch),4位表示对象年龄,年龄后固定为1,表示偏向锁,最近2位为01,表示可偏向/未锁定。

偏向锁示例:

package jvm.chapter08;

import java.util.List;
import java.util.Vector;

/**
 * 使用一个线程对Vector进行写入操作,由于对Vector的访问内部都用同步锁控制,
 * 每次add()操作都会请求numberList对象的锁。
 *
 * @author chengyan
 * @date 2019-11-17 7:41 下午
 */
public class Demo01 {
    public static List<Integer> numberList = new Vector<Integer>();

    public static void main(String[] args) throws InterruptedException {
        long begin = System.currentTimeMillis();
        int count = 0;
        int startnum = 0;
        while(count < 1000_0000) {
            numberList.add(startnum);
            startnum += 2;
            count++;
        }
        long end = System.currentTimeMillis();
        System.out.println(end - begin);
    }
}

使用参数-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0 -client -Xmx512m -Xms512m运行,结果如下:

227

这说明程序用227毫秒完成所有的工作。参数-XX:BiasedLockingStartupDelay表示虚拟机在启动后立即使用偏向锁。如不设置该参数,虚拟机默认会在启动后4秒后,才启用偏向锁,考虑到程序运行时间较短,故做此设置,尽早启用偏向锁。

若禁用偏向锁,则只需使用如下参数启动程序:

-XX:-UseBiasedLocking -client -Xmx512m -Xms512m

结果如下:

363
1.3 轻量级锁的对象头

当对象处于轻量级锁时,其中Mark Word 如下(00表示最后2位的值):

[ptr | 00] locked

此时,它指向存放在获得锁的线程栈中的该对象的真实对象头。

1.4 重量级锁的对象头

当对象处于轻量级锁时,其中Mark Word 如下:

[ptr | 10] monitor

此时,最后2位为10,整个 Mark Word 指向 Minitor的指针。

1.5 普通对象的对象头

当对象处理于普通的未锁定状态时,其格式如下:

[header | 0 | 01|] unlocked

前29位表示对象的哈希值、年龄等信息。倒数第3位为0,最后两位为01,表示未锁定。可以发现,最后两位的值和偏向状态是一样的,此时虚拟机通过倒数第3位来区分是否为偏向锁。

上述内容就是如何理解java中锁与并发,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. 深入理解 MySQL ——锁、事务与并发控制
  2. 怎么理解Java悲观锁与乐观锁

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:有哪些使用SSH的技巧

下一篇:如何理解Linux系统中的root权限控制

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》