首页 > 编程语言 >java 多线程:synchronized 详解

java 多线程:synchronized 详解

时间:2023-05-24 16:24:07浏览次数:53  
标签:java synchronized 代码 计数器 线程 监视器 多线程

总结

  • 一个锁对象只能同时被一个线程持有,分为对象锁和类锁
    • 对象锁:每个对象都可以作为锁(几个不同的对象就是几个锁)
    • 类锁:字节码对象也能作为锁(全局唯一)
  • 同步方法不能自定义锁,只能是默认的锁(非静态:this,静态:class);同步代码块默认的锁和方法一样(非静态:this,静态:class,普通方法里面可以有同步代码块),但是可以自定义锁
  • 同步方法,执行完毕或抛出异常都会释放锁
  • 是重入锁
  • 可以保证 原子性、可见性、有序性

使用

多线程卖票代码

//这个用法就是使用了obj的锁,来锁定一个代码块。
synchronized(obj){
    // some code...
}
//对整个方法上锁,这个时候它使用的是当前实例this的锁,和下面的效果等同
public synchronized void aMethod(){
    // some code...
}
// 普通方法包含同步代码块,这种情况下等同于同步方法
public void aMethod(){
    synchronized(this){
        // some code...
    }
}

加锁原理

每个对象锁或类锁都会有一个 监视器,这个是关键,在对象头中,每个监视器同一时间只能被一个线程获取,根据监视器的锁计数器控制(如果计数器大于1,别的线程就获取不到锁的监视器,当前线程可以重复获取,重入锁)

  • monitor 计数器为0,意味着当前还没有线程获得,当前线程就会立刻获得然后把锁计数器+1,一旦+1,别的线程再想获取,就需要等待
  • 如果这个monitor已经拿到了这个锁的所有权,又重入了这把锁,那锁计数器就会累加,变成2,并且随着重入的次数,会一直累加
  • 这把锁已经被别的线程获取了,等待锁释放

monitorenter 指令让计数器+1,monitorexit 指令让计数器-1
多线程并发执行,怎么使多个线程获取到的监视器的锁计数器是一致的呢?其实就是可见性的实现原理,不清楚,下面有一些说明

原子性

在一次或多次操作中,要么所有的操作都执行,并且不会受其他因素干扰而中断,要么所有的操作都不执行

  • 因为互斥性,同一时间只能一个线程执行这段代码,天然具有原子性

有序性

是指程序代码在执行过程中的先后顺序,由于java在编译器以及运行期的优化,导致了代码的执行顺序未必就是开发者编写代码的顺序

  • 因为互斥性,同一时间只能一个线程执行这段代码,压根不会有成指令重排的问题

可见性

  • https://www.pdai.tech 说是 内存模型和 happens-before
  • 有的说是 lock 指令(写完共享变量后发送一条 lock 的指令,把工作内存的值回写到主内存中)
  • 有的说是内存屏障

jdk1.6 对 synchronized 的优化

其实就是锁膨胀,1.6 之前初始都是重量级锁,1.6 之后做了优化,先是无锁,最后才是重量级锁,具体请看前一篇文章 java 各种锁

标签:java,synchronized,代码,计数器,线程,监视器,多线程
From: https://www.cnblogs.com/hangychn/p/17218555.html

相关文章

  • Java开启异步的两种方式
    二、Java开启异步的两种方式1、注解开启:@Async1.1、配置异步的线程池必须配置异步线程池,否则异步不会生效。@EnableAsync注解:指定异步线程池。不指定默认使用:SimpleAsyncTaskExecutor线程池SimpleAsyncTaskExecutor是一个最简单的线程池,它没有任何的线程相关参数配置,它会为......
  • 用命令行工具运行java文件
     1、若java文件有packagepackagequitStu;publicclassMain{publicstaticvoidmain(String[]args){for(Stringstr:args){if(str.equals("11")){System.out.println("-v1.0");brea......
  • Java如何生成随机数?要不要了解一下!
    前言我们在学习Java基础时就知道可以生成随机数,可以为我们枯燥的学习增加那么一丢丢的乐趣。本文就来介绍Java随机数。一、Random类介绍在Java中使用Random工具类来生成随机数,该类在java.util包下,在JDK1.0版本就存在了。Random单词本身就是随机、随意、任意的意思......
  • Java配置线程池
    一、Java配置线程池1、线程池分类、其他1.1、分类IO密集型和CPU密集型任务的特点不同,因此针对不同类型的任务,选择不同类型的线程池可以获得更好的性能表现。1.1.IO密集型任务​ IO密集型任务的特点是需要频繁读写磁盘、网络或者其他IO资源,执行时间长,CPU占用率较低。对......
  • 流程表单JavaScript代码
    ----订单流程-----------//表单加载初始化时functionpreinit(){}//表单加载完成,isrun代表流程是否流转中1-是,0-否functionLoaded(isrun){$("#om_order_status").attr("disabled","disabled");......
  • java入门2..0
    java的运行原理1.在本地磁盘中创建一个文本文件为Demo.java的源文件2.在源文件中编写java代码如下:publicclassDemopublicstaticvoid,main(String[]args){System.out.println(" ");}3.在当前文件目录下。输入cmd跳转到dos窗口4.通过java编译源文件。会生成字节码文件......
  • 剑指 Offer II 018(Java). 有效的回文(简单)
    题目:给定一个字符串s,验证s 是否是 回文串 ,只考虑字母和数字字符,可以忽略字母的大小写。本题中,将空字符串定义为有效的 回文串 。 示例1:输入:s="Aman,aplan,acanal:Panama"输出:true解释:"amanaplanacanalpanama"是回文串示例2:输入:s="raceacar"......
  • 【JavaWeb-02】Web服务器
    文章目录2.web服务器2.1技术讲解2.2web服务器2.web服务器2.1技术讲解JSP/Servlet:B/S:浏览和服务器C/S:客户端和服务端sun公司主推的B/S架构基于Java语言的(所有的大公司,或者一些开源的组件,都是用Java写的)可以承载三高问题带来的影响2.2web服务器IIS:微软的Tmocat:Java初学人员......
  • 京东数科java一面【过】
    自我介绍实习经历【聊了挺多】集合方面Collection【list(写时复制)/set/Queue(阻塞队列)】Map【HashTable/HashMap/ConcorrentHashMap】synchronized对象头原理的过程A系统1WTBS,B系统300TBS,问解决方法技术角度:读写分离、Kong层、加服务器业务角度:加锁、加进度条AQS是什么原理Volat......
  • 阿里蚂蚁集团Java一面【凉】
    一个小哥哥打来的电话1.自我介绍2.介绍实习实习的时候用到了分布式锁深挖分布式锁的实现【回去复盘】遇到了什么问题?为什么用这个?怎么用的?怎么实现?3.多服务器之间是怎么保持数据一致的【回去复盘】4.分布式事务5.微服务了解嘛【回去复盘】6.MySQL的索引7.MySQL的乐观锁......