栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java笔记——Java并发

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java笔记——Java并发

进程和线程的区别

进程是操作系统分配资源(进程id、虚拟内存,文件、socket资源等等)的最小单元;

线程是操作系统进行任务调度的最小单元,线程隶属于进程。

1,Java如何开启线程?怎么保证线程安全?

开启线程的方法:

1)继承Thread类,实现run方法,调用start方法;

2)实现Runnable接口,实现run方法,通过Thread类或者线程池类启动;

3)实现Callable接口,实现call方法,通过FeatureTask创建线程,可以获取执行结果;

4)通过线程池启动线程。

保证线程安全的方法:

加锁,保证线程的可见性,串行修改共享资源

1)使用JVM提供的锁,即使用synchronized关键字;

2)使用JDK提供的锁,实现了Lock接口的锁,可重入锁,读写锁等。

2,synchronized

Java中每一个对象都是锁,synchronized使用的锁保存在对象头的Mark Word中

synchronized使用有三种形式:

1)修饰普通成员方法,锁是当前实例对象;

2)修饰静态成员方法,锁是当前类的class对象;

3)synchronized代码块,锁是括号中指定的对象。

使用sychronized,加锁和解锁是自动完成的;退出同步方法块,或者同步方法块内抛出异常,会自动释放锁。

在早期(JSE1.6之前的版本)synchronized采用操作系统内核API实现加锁和解锁,性能开销比较高,被称为重量级锁;JSE1.6之后对synchronized进行极大的优化,引入偏向锁、轻量级锁,加锁和解锁性能损耗得到很大的改善。随着锁竞争程度的增加,synchronized使用的锁会从偏向锁升级到轻量级锁,进而升级到重量级锁,锁升级之后不能降级。

Java对象头

32位JVM,1个字是32位;64位虚拟机,1个字是64位。

数组对象,占用3个字宽;

非数组对象,占用2个字宽。

对象头的结构

长度

内容

说明

1个字宽

Mark Word

存hashCode或锁信息等

1个字宽

Class metadata Address

存对象类型数据的指针

1个字宽

Array Length

如果是数组对象,存数组的长度

对象头Mark Word的结构

锁状态

4bit

1bit 是否是偏向锁

2bit 锁标志位

无锁状态

分代年龄

0

01

偏向锁

线程ID+epoch

分代年龄

1

01

轻量级锁

指向栈中锁记录的指针

00

重量级锁

指向互斥量(重量级锁)的指针

10

GC标记

11

对象头里锁的状态不同,对象头Mark Word里各个位存的信息也不同。

偏向锁

大多数情况下,锁不仅不存在竞争,而且总是被同一个线程获得。

在没有竞争的情况下,synchronized使用偏向锁。

轻量级锁

在竞争比较小的时候,synchronized的锁会升级到轻量级锁。

轻量级锁在获取锁不成功的时候,线程不会阻塞,而是自旋,通过CAS操作尝试获取锁。自旋会消耗CPU,当一定次数的自旋还是获取不到锁时,synchronized会将锁升级为重量级锁,线程获取锁不成功时会阻塞等待,同时让出CPU。

synchronized锁的优缺点

优点

缺点

使用场景

偏向锁

加锁和解锁不需要额外的开销,纳秒级可以忽略不计

存在竞争时会发生锁撤销带来开销

只有一个线程访问同步块(单例模式初始化实例)

轻量级锁

竞争的线程不会阻塞,提高了响应速度

如果始终得不到锁,自旋会消耗CPU

追求响应时间

同步块执行非常快

重量级锁

竞争的线程阻塞不自旋,不消耗CPU

线程阻塞,响应速度慢

追求吞吐量

同步块执行比较长

Java对象内存布局

使用openjdk的jol-core工具包


    org.openjdk.jol
    jol-core
    0.10

场景一

第一次输出是无锁状态;第二次输出是轻量级锁状态。

场景二

 

第一次输出是无锁状态;第二次o2并没有加锁,输出偏向锁状态,但是Mark Word没有记录持有锁的线程id;第三次o2加锁后,输出偏向锁状态,Mark Word有记录持有锁的线程id。第四次同步代码块执行完之后o2上的锁应该已经释放,但是仍然输出的是偏向锁状态,Mark Word也记录着线程id,并没有撤销锁,注意当存在其他线程竞争时才会撤销偏向锁,如果竞争激烈会升级到轻量级锁或者重量级锁。

关于第二次输出结果的说明,JVM的一个特性

synchronized不响应中断异常

synchronized获取锁时,如果没有竞争到锁线程阻塞后,不会响应中断异常。

JDK中实现Lock接口的锁,使用lockInterruptibly方法能够响应中断异常。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/306372.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号