线程基础知识 03 synchronized锁(对象在内存的布局和加上锁后对象在内存中的变化)
1 线程不安全演示
public class ThreadAndLockTest1 {
private static int a = 0;
public static void main(String[] args) throws InterruptedException {
CountDownLatch la = new CountDownLatch(2);
for (int t = 0;t < 2;t++){
new Thread(()->{
for (int i = 0;i < 100000;i++) {
a++;
}
la.countDown();
}).start();
}
la.await();
System.out.println(a);
}
}
如果线程安全,那么打印结果应该是200000
执行结果,发现不是期望的结果,说明线程不安全
149202
2 锁演示
上面代码加上锁(synchronized)之后
public class ThreadAndLockTest1 {
private static int a = 0;
public static void main(String[] args) throws InterruptedException {
CountDownLatch la = new CountDownLatch(2);
for (int t = 0;t < 2;t++){
new Thread(()->{
synchronized (ThreadAndLockTest1.class){
for (int i = 0;i < 100000;i++) {
a++;
}
}
la.countDown();
}).start();
}
la.await();
System.out.println(a);
}
}
执行结果,是期望的结果
200000
3 对象在内存里面的存储布局(Oracle的虚拟机)
什么东西可以作为一把锁?在解释这个问题之前,先了解对象是由什么构成的?
3.1 它主要分为三个部分
对象头:对象头又包括两类:markword,class pointer,
实例数据:instance data,
对齐填充:padding

3.2 markword
它的大小是8字节
1)哈希码、
2)GC年龄分代、
3)锁的信息
锁状态标志
线程持有的锁、
偏向线程id
偏向时间戳
3.3 使用JOL查看对象内存
https://www.cnblogs.com/jthr/p/15980849.html
4 查看上锁对象在内存中布局
上面我们知道了对象的组成和怎么去看对象中的布局,现在我们来看下对象在上锁前、上锁中、上锁后的变化
4.1 示例代码
public class JolTest {
static class T{
}
public static void main(String[] args) {
T o = new T();
System.out.println(ClassLayout.parseInstance(o).toPrintable());
synchronized (o){
System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
}
4.2 执行结果
发现上锁后对象头中的markword发生的变化,解锁后又恢复了。
上锁实际上是在对象头上做了个标记


001代表无锁
00代表轻量级锁
线程基础知识 03 synchronized锁(对象在内存的布局和加上锁后对象在内存中的变化)的更多相关文章
- Java并发编程(一):线程基础知识以及synchronized关键字
1.线程与多线程的概念:在一个程序中,能够独立运行的程序片段叫作“线程”(Thread).多线程(multithreading)是指从软件或者硬件上实现多个线程并发执行的技术. 2.多线程的意义:多线 ...
- java线程基础知识----线程与锁
我们上一章已经谈到java线程的基础知识,我们学习了Thread的基础知识,今天我们开始学习java线程和锁. 1. 首先我们应该了解一下Object类的一些性质以其方法,首先我们知道Object类的 ...
- 《Java基础知识》Java锁详解(volatile,synchronized等)
volatile: 让变量每次在使用的时候,都从主存中取. volatile具有synchronized关键字的“可见性”,但是没有synchronized关键字的“并发正确性”,也就是说不保证线程执 ...
- Java线程基础知识(状态、共享与协作)
1.基础概念 CPU核心数和线程数的关系 核心数:线程数=1:1 ;使用了超线程技术后---> 1:2 CPU时间片轮转机制 又称RR调度,会导致上下文切换 什么是进程和线程 进程:程序运行资源 ...
- java线程基础知识----线程基础知识
不知道从什么时候开始,学习知识变成了一个短期记忆的过程,总是容易忘记自己当初学懂的知识(fuck!),不知道是自己没有经常使用还是当初理解的不够深入.今天准备再对java的线程进行一下系统的学习,希望 ...
- java多线程中篇(二) —— 线程的创建和Synchronized锁关键字
学习之前,先了解线程状态图 说明:线程共包括以下5种状态. 1. 新建状态(New) : 线程对象被创建后,就进入了新建状态.例如,Thread thread = new Thread ...
- Java 线程基础知识
前言 什么是线程?线程,有时被称为轻量进程(Lightweight Process,LWP),是程序执行流的最小单元.一个标准的线程由线程 ID,当前指令指针 (PC),寄存器集合和堆栈组成.另外,线 ...
- Java并发之线程管理(线程基础知识)
因为书中涵盖的知识点比较全,所以就以书中的目录来学习和记录.当然,学习书中知识的时候自己的思考和实践是最重要的.说到线程,脑子里大概知道是个什么东西,但很多东西都还是懵懵懂懂,这是最可怕的.所以想着细 ...
- Java__线程---基础知识全面实战---坦克大战系列为例
今天想将自己去年自己编写的坦克大战的代码与大家分享一下,主要面向学习过java但对java运用并不是很熟悉的同学,该编程代码基本上涉及了java基础知识的各个方面,大家可以通过练习该程序对自己的jav ...
- Java并发(基础知识)——显示锁和同步工具类
显示锁 Lock接口是Java ...
随机推荐
- CSP-J2022 题解报告
\(CSP-J2022\) 题解报告 \(T1\) 乘方: 发现 \(2^{32}>10^9\),所以这个题只需要特判 \(a=1\) 的情况为 \(1\),其他直接枚举再判断即可. Code: ...
- 基于Spring-AOP的自定义分片工具
作者:陈昌浩 1 背景 随着数据量的增长,发现系统在与其他系统交互时,批量接口会出现超时现象,发现原批量接口在实现时,没有做分片处理,当数据过大时或超过其他系统阈值时,就会出现错误.由于与其他系统交互 ...
- 对于函数极限存在的充要条件“lim f(x)=A互推f(x)=A+a(x) lim a(x)=0”补充解释
毫无疑问,这个定义适用于任何函数极限,诺f(x)有去间断点的时候,a(x)也为可去间断点函数. 例:
- Cacheable VS Non-Cacheable
1 基本概念 在嵌入式软件开发中,经常会碰到说某块内存是cache的,还是non-cache的,它们究竟是什么意思?分别用在什么场景?non-cache和cache的内存区域怎么配置?这篇博文将会围绕 ...
- 动态规划篇——线性DP
动态规划篇--线性DP 本次我们介绍动态规划篇的线性DP,我们会从下面几个角度来介绍: 数字三角形 最长上升子序列I 最长上升子序列II 最长公共子序列 最短编辑距离 数字三角形 我们首先介绍一下题目 ...
- WebApi如何启用Session并且使用
首先打开项目的Global.asax文件,重新方法init public override void Init() { //注册事件 this.AuthenticateRequest += WebAp ...
- MySQL遇到的坑:sql_mode=only_full_group_by不兼容
描述: 解决方案: show variables like "%sql_mode%"; SET sql_mode=(SELECT REPLACE(@@sql_mode," ...
- 数据结构高阶--AVL(平衡二叉树)(图解+实现)
AVL树(平衡二叉树) 概念 二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下.因此为了解决这个问题,两位俄罗斯的数学家发明 ...
- 【中间件】Docker
一.Docker (一)基础概念 1.概念 是linux容器的一种封装,它是最流行的Linux容器解决方案,由go语言开发 提供简单易用的容器使用接口,方便创建.使用和销毁 2.应用场景 自动打包.持 ...
- 缓存管理器CacheManager使用
缓存管理器CacheManager 一.背景 代码并发量因建行活动页上升,大量请求打到Mongo导致数据库cpu100%从而服务不可用,目前解决方案,使用编程式缓存,即对缓存的操作与业务代码耦合. ...