当前位置: 首页 > news >正文

网站的版权信息澄海手工外发加工网

网站的版权信息,澄海手工外发加工网,郑州seo线上推广系统,建设淘宝联盟购物网站文章目录一、 线程安全问题二、synchronized简介1) 原子性2) 可见性3) 有序性4)可重入1. 什么是synchronized2.什么是同步3.synchronized的特性4.synchronized的实现原理(了解即可)三、synchronized的用法1. 同步方法2. 同步代码块四、对象锁和类锁1)对象锁2)类锁1.对象锁的探索… 文章目录一、 线程安全问题二、synchronized简介1) 原子性2) 可见性3) 有序性4)可重入1. 什么是synchronized2.什么是同步3.synchronized的特性4.synchronized的实现原理(了解即可)三、synchronized的用法1. 同步方法2. 同步代码块四、对象锁和类锁1)对象锁2)类锁1.对象锁的探索2.对象锁的简介1.对象锁的验证2.类锁的验证3.对象锁和类锁的区别一、 线程安全问题线程安全问题使我们平时面试中总避不开会谈论的一个点通常情况下线程安全问题都是由于非方法内的实例变量引起的。就比如我们举个很简单的例子在描述线程的相关Demo中我喜欢用银行相关的业务场景做举例大多数和线程相关的知识点都能对应到银行需要用到的业务。就比如今天我会通过一个简单的银行排号系统的实现来解释今天的知识点。代码实现public class BankLineUp {// 设置一个当天最大服务人次public static final Integer MAX_NUM 500;// 设置一个排号计数器public static Integer count 0;// 创建一个内部类 实现runnable接口class LineUp implements Runnable {// 叫号逻辑实现Overridepublic void run() {// 输出当前叫到的号码call();}}// 提供构造方法public LineUp lineUp() {return new LineUp();}public static void main(String[] args) { BankLineUp bankLineUp new BankLineUp();new Thread(bankLineUp.lineUp(), 一号窗口).start();new Thread(bankLineUp.lineUp(), 二号窗口).start();new Thread(bankLineUp.lineUp(), 三号窗口).start();}// 通过synchronized修饰方法实现同步方法public void call() {while (true) {if (count MAX_NUM) {try {// 通过休眠一秒 模拟系统延时 Thread.sleep(1l); System.out.println(有请 count 号顾客到 Thread.currentThread().getName() 办理业务!);} catch (InterruptedException e) { e.printStackTrace();}} else {break;}}}}运行结果:上面的案例我们模拟了因为系统可能存在的延时而导致了叫号系统处理了超过自己限制的数据量,这明显是线程不安全的,那么我们有没有简单的方式可以解决这个小问题呢?二、synchronized简介1. 什么是synchronizedsynchronized的字面翻译就是同步Java通过引入synchronized的关键字来保证同一时间只有一个线程可以运行被synchronized保护的代码。2.什么是同步同步指的是为了完成某种任务而建立的两个或多个进程,这些进程因为要在某些位置上协调他们的工作次序而瞪大,传递信息所产生的制约关系,因此同步又叫做直接制约关系。在Java线程中的同步主要就体现在如果该资源为同步资源程为了防止多个线程访问该资源时对数据对象产生破坏CPU在调度该资源时一次仅允许一个线程访问修改。3.synchronized的特性1) 原子性所谓的原子性指的是同一个或者多个操作要么全部执行,要么全部不执行2) 可见性可见性就是指多个线程访问同一个资源时,该资源状态及变化对其他线程可见。3) 有序性有序性指的是CPU对于线程的执行顺序与代码顺序相同。JAVA允许编译器和处理器对于指令进行重排序指令重排序并不会影响单线程的执行结果。但是在多线程中由于存在半初始化线程指令重排会造成很难排查的线程安全问题。4)可重入当一个线程师徒操作一个由其他线程持有锁的临界资源时将会出于阻塞状态当一个线程再次请求自己持有对象锁的资源时无需等待这种现象叫做可重入锁。4.synchronized的实现原理(了解即可)synchronized是在对象头里面存储一个ACC_SYNCHRONIZED标识进行实现的当JVM进入和退出一个Monitor对象的时候会判断此时的monitor是否被持有如果被持有则它将会处于锁定状态。在汇编指令中monitorenter和monitorexit分别代表获得和释放持有的monitor对象锁三、synchronized的用法1. 同步方法在刚刚的例子里我们发现了共享变量在多线程访问的情况下会出现线程安全问题之后又引出了synchronized关键字那么这个关键字该如何用来解决线程安全问题我们可以看下面的一段代码package xiao.thread.synchronize;/** * Title: BankLineUp.java * Package xiao.thread.synchronize * Description: TODO * author: 晓 * date: 2020年11月30日 上午10:15:36 * version V1.0 * Copyright: com.cdzg.com * */public class BankLineUp {// 设置一个当天最大服务人次public static final Integer MAX_NUM 500;// 设置一个排号计数器public static Integer count 0;// 创建一个内部类 实现runnable接口class LineUp implements Runnable {// 叫号逻辑实现Overridepublic void run() {// 输出当前叫到的号码call();}}// 提供构造方法public LineUp lineUp() {return new LineUp();}public static void main(String[] args) { BankLineUp bankLineUp new BankLineUp();new Thread(bankLineUp.lineUp(), 一号窗口).start();new Thread(bankLineUp.lineUp(), 二号窗口).start();new Thread(bankLineUp.lineUp(), 三号窗口).start();}// 通过synchronized修饰方法实现同步方法public synchronized void call() {while (true) {if (count MAX_NUM) {try {// 通过休眠一秒 模拟系统延时 Thread.sleep(1l); System.out.println(有请 count 号顾客到 Thread.currentThread().getName() 办理业务!);} catch (InterruptedException e) { e.printStackTrace();}} else {break;}}}}执行结果:代码变化:我们仅仅是在call的方法体上加了一个synchronized关键字就实现了线程变量的保护,从而达到线程安全的目的,但是新的问题新出现了:由于call方法被设置为了同步方法,此时二号线程和三号线程一直在等待一号线程执行完才能拿到cpu的执行权,但是所有的变量此时都被一号线程处理完毕,二号和三号线程并没有实际的参与到代码的运行中,由此可见当我们在将方法添加synchronized后,同步方法的锁力度太大了,已经影响了我们的运行效率,那么此时有没有办法对这个问题进行简单的优化呢?2. 同步代码块public class BankLineUp {// 设置一个当天最大服务人次public static final Integer MAX_NUM 500;// 设置一个排号计数器public static Integer count 0;// 创建一个内部类 实现runnable接口class LineUp implements Runnable {// 叫号逻辑实现Overridepublic void run() {// 输出当前叫到的号码call();}}// 提供构造方法public LineUp lineUp() {return new LineUp();}public static void main(String[] args) { BankLineUp bankLineUp new BankLineUp();new Thread(bankLineUp.lineUp(), 一号窗口).start();new Thread(bankLineUp.lineUp(), 二号窗口).start();new Thread(bankLineUp.lineUp(), 三号窗口).start();}// 通过synchronized修饰方法实现同步方法public void call() {while (true) {synchronized (this) {if (count MAX_NUM) {try {// 通过休眠一秒 模拟系统延时 Thread.sleep(1l); System.out.println(有请 count 号顾客到 Thread.currentThread().getName() 办理业务!);} catch (InterruptedException e) { e.printStackTrace();}} else {break;}}}}}运行结果:在我们将call方法的同步粒度从整个方法体变成方法中的一个代码块的时候,有效的解决了线程等待方法运行结束才能获得方法锁的问题。那么此时有个小的疑问困扰着我同步方法和同步方法体使用的是否是统一把锁来控制同步代码的运行四、对象锁和类锁1.对象锁的验证1.对象锁的探索为了验证我的疑问首先需要写一个小的demopublic class ObjectLock {public static void main(String[] args) { ObjectLock objectLock new ObjectLock();new Thread(() - { objectLock.call();}, 一号线程).start();new Thread(() - { objectLock.speak();}, 二号线程).start();}// 同步方法 通过死循环使同步方法不会退出public synchronized void call() { System.out.println(Thread.currentThread().getName() :开始运行);while (true) {}}// 同步代码块public void speak() {synchronized (this) {try { System.out.println(Thread.currentThread().getName() :开始运行);// 通过sleep延长方法执行时间 Thread.sleep(100_000); System.out.println(Thread.currentThread().getName() :运行结束);} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();}}}}然后打开cmd窗口输入jps命令拿到此时执行线程的线程号然后输入jstack pid 命令查看线程状态在这里我们可以看到同步方法call()获取了0x0000000780676b40这把锁而此时使用了同步代码块的方法speak()也在等待获取0x0000000780676b40这把锁因此可以看出在一个对象中同步方法和同步代码块使用的是同样的锁。在同步代码块中我们传入了一个参数this它代表了我们为当前的对象添加了锁也就是给同步代码块上了对象锁。类声明后我们可以 new 出来很多的实例对象。这时候每个实例在 JVM 中都有自己的引用地址和堆内存空间这时候我们就认为这些实例都是独立的个体很显然在实例上加的锁和其他的实例就没有关系互不影响了。2.对象锁的简介对象锁也叫方法锁是针对一个对象实例的它只在该对象的某个内存位置声明一个标识该对象是否拥有锁所有它只会锁住当前的对象而并不会对其他对象实例的锁产生任何影响。为了验证对象锁是否会影响其他对象这个事情我们将main方法的对象实例进行更换 public static void main(String[] args) { ObjectLock objectLock new ObjectLock(); ObjectLock objectLock2 new ObjectLock();new Thread(() - { objectLock.call();}, 一号线程).start();new Thread(() - { objectLock2.speak();}, 二号线程).start();}运行结果此时二号线程可以无视一号线程持有锁进行的死循环而直接运行也就证明了我们说的对象锁的影响范围仅为当前对象。或者我们还可以采用下面将参数this更换为其他对象的方式解决 public void speak() {synchronized (new String()) {try { System.out.println(Thread.currentThread().getName() :开始运行);// 通过sleep延长方法执行时间 Thread.sleep(100_000); System.out.println(Thread.currentThread().getName() :运行结束);} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();}}}12345678910111213这里需要注意的一点我在这里使用的是new String() 的方式来创建新的对象当做锁如果此时直接传入的是一个字面量为abc的字符串那么此时该同步代码块所持有的将不再是对象锁而是类锁。2.类锁的验证那么什么是类锁按照惯例我们还是写个小demo来做验证public class ObjectLock {public static void main(String[] args) {//分别创建两个对象来调用同步方法 以避免对象锁的干扰 ObjectLock objectLock01 new ObjectLock(); ObjectLock objectLock02 new ObjectLock();new Thread(()-{objectLock01.test();},一号线程).start();new Thread(()-{objectLock02.test();},二号线程).start();}public void test() {synchronized (ObjectLock.class) { System.out.println(Thread.currentThread().getName(): start);while(true) {}}}}123456789101112131415161718还是用jstack命令来观察:此时二号线程和一号线程持有的锁相同,证明此时所有ObjectLock对象的实例都持有该锁。类锁是加载类上的而类信息是存在 JVM 方法区的并且整个 JVM 只有一份方法区又是所有线程共享的所以类锁是所有线程共享的。3.对象锁和类锁的区别参考文章https://zhuanlan.zhihu.com/p/981457131)对象锁通常我们使用实例锁的方式有下面三种1、 锁住实体里的非静态变量非静态变量是实例自身变量不会与其他实例共享所以锁住实体内声明的非静态变量可以实现对象锁。锁住同一个变量的方法块共享同一把锁。2、锁住 this 对象this 指的是当前对象实例本身所以所有使用 synchronized(this)方式的方法都共享同一把锁。3、直接锁非静态方法2)类锁类锁是所有线程共享的锁所以同一时刻只能有一个线程使用加了锁的方法或方法体不管是不是同一个实例。类锁主要应用在下面的情况中1、锁住类中的静态变量因为静态变量和类信息一样也是存在方法区的并且整个 JVM 只有一份所以加在静态变量上可以达到类锁的目的。2、直接在静态方法上加 synchronized因为静态方法同样也是存在方法区的并且整个 JVM 只有一份所以加在静态方法上可以达到类锁的目的。3、锁住 xxx.class对当前类的 .class 属性加锁可以实现类锁。
http://www.zqtcl.cn/news/696340/

相关文章:

  • 做网站的语北京比较好的it公司
  • 长春建站模板制作php项目开发案例源码
  • 绍兴seo外包公司山东网站建设优化
  • php做网站知乎境外网站icp备案
  • 做seo网站图片怎么优化地坪漆东莞网站建设技术支持
  • wordpress theme forest济南优化网站排名
  • 简述网站的制作步骤合肥网站建设需
  • 网站备案的程序哪里能买精准客户电话
  • 白云网站建设网站版式
  • 做美食有哪些网站科技公司介绍
  • 网站后台被百度蜘蛛抓取哪个做网站比较好
  • 企业建设网站的需求分析百度免费发布信息平台
  • 网站建设交易中心上海装修公司排行榜
  • 桂林论坛网站有哪些在线设计平台用户分析
  • wap网站的开发去加网 wordpress
  • 博客网站建设设计论文总结php mysql做网站登录
  • 海南智能网站建设公司wordpress 如何使用php版本号
  • 河南网站开发培训app 软件开发
  • 购物网站功能介绍一流的高密网站建设
  • 电影网站怎么做优化wordpress 去掉w
  • 永久网站空间标书制作员工资很低吗
  • 做网站用到ps么淘宝优惠网站怎么做
  • jsp 淘宝网站验证码 设计搜索引擎排名
  • pdf怎么做电子书下载网站北京成立公司
  • 网站后台附件无法上传阿克苏建设网站
  • 网站和网址有什么不同佛山狮山网站建设
  • 有免费的微网站是什么可以做长图的网站
  • 南昌手机建站模板18种禁用软件黄app
  • 备案的域名做电影网站wordpress伪静态cdn配置
  • 国家城乡住房建设部网站百度关键词首页排名