理论层面:

内置锁与互斥锁

修饰普通方法、修饰静态方法、修饰代码块

demo如下:

package com.roocon.thread.t3;

public class Sequence {
private static int value; // synchronized放在普通方法上,内置锁就是当前方法的实例
public synchronized int getNext(){
return value++;
} // synchronized修饰静态方法,内置锁就是当前的Class字节码对象Sequence.class
public static synchronized int getPrevious(){
return value--;
} public int xx(){
// synchronized修饰静态代码块,则锁的是任意一个对象
/*
synchronized (this){ }
synchronized (Integer.valueOf(value)) { }
synchronized (Sequence.class) { }
*/
synchronized (Sequence.class) {
if (value > 0) {
return value;
}else {
return -1;
}
}
}
public static void main(String[] args) {
Sequence sequence = new Sequence();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName()+" "+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName()+" "+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName()+" "+sequence.getNext());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}

jvm层面:

查看xx方法同步代码块字节码:

查看同步方法字节码:

任何对象都可以作为锁,那么锁信息又存在对象的什么地方呢?

存在对象头中。

对象头中的信息:

  Mark Word

  Class Metadata Address 类的类型地址

  Array Length

1.偏向锁:

每次获得锁和释放锁会浪费资源(消耗时间),很多情况下,竞争锁不是由多个线程,而是由一个线程在使用。线程在获取锁时,会依据对象头Mark word信息进行判断执行。

对象头Mark word中会保存如下信息:

  线程id

  Epoch

  对象的分代年龄信息

  是否是偏向锁

  锁标志位

偏向锁在获取锁之后,如果没有竞争,也就是一直是这个线程在获取锁,那么当这个线程第二次再来进入该方法时,不需要再去获取锁了,也不需要释放锁,这样,就节省了大量的获取锁释放锁的资源。那么,什么时候会释放锁呢?只有当存在竞争时,才会去释放锁。

偏向锁适用于什么场景?

只有一个线程在访问同步代码块的场景。

2.轻量级锁:可以同时让多个线程进入同步代码块。自旋锁就是轻量级锁。

轻量级锁是如何加锁的?

在线程执行同步代码块之前,jvm会先在当前线程的栈帧中创建用于存储锁记录的存储空间。

(栈帧是什么?虚拟机栈中存储的是一个一个的栈帧,栈帧中存储了方法的执行信息,每个方法都会伴随着栈帧的进栈和出栈)

然后呢,并将对象头中的mark word复制到锁记录中。然后呢,开始竞争锁就可以了。竞争成功之后,markword就改变了,会将锁标志位改成轻量级锁。接着,开始执行同步体。

另外一个线程也想获得该锁。同样,它也将对象头中的mark word复制到锁记录中,它发现已经被其他线程获得了锁,所以它修改不成功。于是,它就不停的去修改,不停的失败,直到第一个线程把这个锁释放了,它就可以修改成功了。刚才这一个过程,就是所谓的自旋锁。

3.重量级锁

什么是重量级锁?就是,这个线程获得锁进入之后,其他线程必须在外面等待。synchronized就是重量级锁。

最新文章

  1. 手把手教你做个人 app
  2. Javascript实现的2048
  3. Android学习笔记(二)——探究一个活动
  4. matlab中各种高斯相关函数
  5. img_jquerydim
  6. ModelSim仿真
  7. python学习的一些感悟
  8. BZOJ 1296: [SCOI2009]粉刷匠( dp )
  9. LXC学习实践(3)快速体验第一个容器
  10. QTP 自动化测试--定义变量
  11. jQuery 初知
  12. java使用StringBuilder的方法反转字符串输出
  13. php 对中文字符串的处理- 随机取出指定个数的汉字
  14. C# Monitor的Wait和Pulse方法使用详解
  15. 第九章 词典 (e)桶/计数排序
  16. 【转】TeXmacs:一个真正“所见即所得”的排版系统
  17. 53.storm简介
  18. Rafy中的IOC
  19. 1.高并发教程-基础篇-之nginx负载均衡的搭建
  20. VS2017MVC+EF+MySQL环境搭建

热门文章

  1. Go 实现短 url 项目
  2. windows下批处理保留指定日期下的文件
  3. springcloud源码解析(目录)
  4. djangoNotes
  5. 【小顶堆的插入构造/遍历】PatL2-012. 关于堆的判断
  6. 华为OJ:字符串处理
  7. 【转】用 Consul 来做服务注册与服务发现
  8. c++两种字符串赋值方式 并介绍 C语言下遍历目录文件的方式
  9. DOM属性获取、设置、删除
  10. @JsonSerialize @JsonIgnoreProperties @JsonIgnore @JsonFormat