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

手机老是下载一些做任务的网站建设020网站需要多少钱

手机老是下载一些做任务的网站,建设020网站需要多少钱,北京丰台网站优化,播视频网站开发synchronized是什么synchronized是Java关键字,为了维护高并发是出现的原子性问题。技术是把双刃剑,多线程并发给我带来了前所未有的速率,然而在享受快速编程的过程,也给我们带来了原子性问题。如下:public class Main …

synchronized是什么

synchronized是Java关键字,为了维护高并发是出现的原子性问题。技术是把双刃剑,多线程并发给我带来了前所未有的速率,然而在享受快速编程的过程,也给我们带来了原子性问题。

如下:

public class Main {private static int i = 0;public static void main(String[] args) throws InterruptedException {Main main = new Main();Thread a = new Thread(() -> {main.add10K();}, "A");  // 线程AThread b = new Thread(() -> {main.add10K();}, "B");  // 线程Ba.start();  // 启动线程Ab.start();  // 启动线程Ba.join();   // 等待线程A执行完毕b.join();   // 等待线程B执行完毕System.out.println(i); // 打印i的值,期望20000}// +10000操作public void add10K(){for (int j = 0; j < 10000; j++) {i++;}}
}

上面的程序,你细细品味一下结果会是多少?然后再回来看下面的结果。或者自己编程一下上面的代码,然后带着思考运行一下(面试高频点)。






下面的分析请耐心看,并思考。这就是面试要跟面试官聊的东西,聊越多,聊越细,证明你思考得越多。

答案是小于20000,其实了解过JVM的同学都知道,i++在CPU中其实不是一条CPU指令,而是三条。

  1. 读取i的值;

  1. 对i进行+1操作;

  1. 装载i的值。

那么多线程并发,其实就是每个线程分配一个时间片执行,时间片执行完毕后就轮到下一个线程。在上面的程序,可能会发生的事情:当线程A做到第2步的时候(对i进行+1操作),可能时间片得分给线程B了,此时线程A和线程B假设都读到i的值为0,这时线程B对i进行了+1操作后i的值为1,然后轮到线程A执行,线程A此时到了第三步,把刚才i+1的值装载回去(i=1)。问题就在这了,期望两个线程对i都+1后,期望值应该为2,然而此时却为1。这种情况还不少见,所以导致最终的结果小于期望值20000。

那么怎么解决这个问题呢?通过上面得分析我们知道,就是操作系统搞着时间片轮转运行造成的,不要轮转不就行了,确实可以。但是如果这么做了,又回到单线程时代,况且现在已经不是单核时代了,每个人得电脑至少双核起步吧,所以思路是对的,但是现实场景是骨感的。那么有没有一个可能,就是在线程A对i进行+1操作的时候,我把i这个参数给他锁住,先不要让别的线程操作它呢?这就对了,现在的synchronized、Lock就是这个思想,在操作某个变量时,我先在这个变量前面加个"栅栏"(也可以理解成锁),只有当我撤了这个栅栏(或者撤了这把锁),其他人才可以对这个变量进行操作,这不就没什么问题了。

synchronized其实就是利用这个原理做的这个关键字,但是它是隐式的,没有展现出来,但是其实在底层的"汇编指令",它其实是有展现的,带你们看一下。


这是Java代码

public class Main {public static void main(String[] args) throws InterruptedException {}public void operate(){synchronized(this){}}}

这是"汇编指令",JVM自己约定的汇编指令,所以我加了双引号。(这个是通过:Javap -c Main.class指令得到的,大家有兴趣可以试试!)

可以看到上图,我画圈圈的东西,monitorenter、monitorexit、monitorexit,这其实就是synchronized的两个隐式"锁"指令了,monitorenter代表加锁,monitorexit代表解锁。为什么monitorexit有两个呢?原因其实也很简单,为了预防死锁用的,因为我们正常情况下当然是一个解锁就可以了,万一没运行到解锁那一行,程序挂了呢?那此时是不是在异常时设置一条解锁会好点?所以两个monitorexit是有道理的!


synchronized作用范围

锁非静态方法

public class Main {public static void main(String[] args) throws InterruptedException {}public synchronized void operate(){}}

像上面的程序,锁的就是方法,这个方法是来源某个实例的,所以根据传递原则,其实锁的就是你new出来的那个实例,应该很好理解。下面来个例子,带你走走坑。

这个程序代码务必认真看,比你看100篇synchronized讲解有用!因为很多都是走马观花,没有落实到具体实践讲解,只让你知道锁的是实例,而实际场景中遇到的坑,你可能自己都理所当然,不知所以。


public class Main {public static void main(String[] args) throws InterruptedException {A a = new A();B b = new B();a.addMoney(b.money);}}class A {public Integer money = 100;public synchronized void addMoney(Integer targetMoney){money += targetMoney;System.out.println(money);}}class B {public Integer money = 200;}

问题:假设在执行addMoney方法的时候,有其他线程修改了B的money为300,那么addMoney执行的结果是什么呢?

思考一下,可以评论区说一下答案+理解,这个真的很重要。这是synchronized最关键的点了,我先设个坑,评论区回答认真看的,因为真的很重要、很重要、很重要。


非静态代码块


public class Main {public static void main(String[] args) throws InterruptedException {A a = new A();B b = new B();a.addMoney(b.money);}}class A {public Integer money = 100;public void addMoney(Integer targetMoney){synchronized(this){money += targetMoney;System.out.println(money);}}}class B {public Integer money = 200;}

跟锁非静态方法其实一样的,就是锁的实例,也存在上面的问题,所以说他真的很重要,笔试很容易就把分丢了,面试很容易就把印象说没了。


public class Main {public static void main(String[] args) throws InterruptedException {A a = new A();B b = new B();a.addMoney(b.money);}}class A {public Integer money = 100;public void addMoney(Integer targetMoney){synchronized(Main.class){money += targetMoney;System.out.println(money);}}}class B {public Integer money = 200;}

这个就不一样了哦,我换成了Main.class,说明锁的是对象,那么有关该对象的变量和方法都会被锁住哦,其他形成访问该类的东西时,都会阻塞,等待该线程释放锁。


锁静态方法


public class Main {public static void main(String[] args) throws InterruptedException {A a = new A();B b = new B();a.addMoney(b.money);}}class A {public Integer money = 100;public static void addMoney(Integer targetMoney){synchronized(Main.class){}}}class B {public Integer money = 200;}

这个跟锁静对象一样,锁的就是类,解释如上。


synchronized的优化

JDK1.6之后,JDK有对synchronized关键字进行了优化,主要是做了一些锁升级的过程:无锁--偏向锁--轻量级锁--重量级锁。

好好读下文,这个也很重要,不懂评论区留言,看到必回!

反向思考一下,加这个synchronized是为了干嘛?不就是为了当某个线程操作某个变量的时候,不然其他线程操作该变量吗?那就是阻塞咯。这个阻塞其实也就是我们上面一直讲解的重量级锁,确实一开始就是这样(JDK1.6之前)。那这很损耗性能的耶,所以搞JDK那群家伙就开始想办法优化这些思想了,我把synchronized做成一个动态化锁。


无锁

如果程序不会造成线程安全的,那我把synchronized去掉,变成无锁化。如下程序,只对i进行读操作,我锁它干嘛?


public class Main {public static void main(String[] args) {A a = new A();a.readI();}}class A {public Integer i = 100;public synchronized void readI(){System.out.println(i);}}

看似有锁,其实我们从"汇编指令"看,已经被JDK偷偷优化成无锁了。


偏向锁

但是实际场景可不是一直读哦,也会有某个线程一直在那里频繁的写写写,但是也无所谓啦,以为就你这个线程是把,那我就在实例对象头那里,直接把偏向锁ID,设置成你这个线程ID就可以了,只要是你这个家伙来访问这个变量,我直接也把锁优化掉。

Idea开启偏向锁VM参数:-XX:+UseBiasedLocking,偏向锁开启后,默认是4秒才会生效


没有等4秒直接用,没使用到偏向锁(non-biasable)

public class Main {public static void main(String[] args) throws InterruptedException {//        TimeUnit.SECONDS.sleep(5);A a = new A();new Thread(()->{a.writeI();}).start();// 打印一下加锁后的实例a的对象头信息System.out.println(ClassLayout.parseInstance(a).toPrintable());}}class A {public Integer i = 100;public synchronized void writeI(){i += 1;}}

这里顺带说一下,对象头的打印是使用了ClassLayout工具类,可以在maven添加以下两个依赖使用

<dependencies><!--查看对象头工具--><dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.9</version></dependency><dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.16</version></dependency>
</dependencies>

等待4秒,使用偏向锁,value为偏向锁ID

public class Main {public static void main(String[] args) throws InterruptedException {TimeUnit.SECONDS.sleep(5);A a = new A();new Thread(()->{a.writeI();}).start();// 打印一下加锁后的实例a的对象头信息System.out.println(ClassLayout.parseInstance(a).toPrintable());}}class A {public Integer i = 100;public synchronized void writeI(){i += 1;}}

轻量级锁

偏向锁其实指的是一般都是某个线程进行变量操作,但是实际场景其实是有多个线程进行操作的,因此在其他线程检查操作的对象头不是自己的ID时,通过CAS尝试再次获取锁,获取不到则转变成轻量级锁,获取到了就还是偏向锁。


重量级锁

这个场景一般是高并发时,都是重量级,因为有多个线程同时操作同个共享资源。如果按锁的锁的升级流程,无非就是浪费时间。


以上则是synchronized的所有概述,欢迎共勉。

http://www.yayakq.cn/news/688573/

相关文章:

  • 天津 交友 网站建设做业务的网站
  • linuxvps建站教程青岛企业名录大全
  • 商务网站创建经费预算网站建设的运营计划
  • 用php源码如何建设网站浏览器游戏网址
  • 电商网站建设论文参考文献wordpress 主页 插件
  • 怎么快速推广网站如何设置中国建设银行网站
  • 专业做网文的网站有哪些苏州网站建设哪家快
  • 上海专业网站建设费用wordpress在线安装
  • 电商网站建设懂你所需杭州建设网考试信息网
  • 监理企业建设部网站年报工程项目信息
  • 六安建设机械网站优秀集团网站
  • qt 可以做网站吗最火的传奇手游网站
  • 张槎网站设计杭州建设工程交易网
  • 手机触屏版网站管理系统仿v电影wordpress
  • wordpress检查全站链接wordpress两步验证码
  • 网站设计规划范文建个大型网站要多少钱
  • 肇东网站建设云聚达网站建设考评表
  • 十三五关于网站建设免费下载微信2023
  • 网站备案初审过了建筑工程信息网站
  • 做本地房产网站wordpress小程序扫码登录
  • 深圳建站公司优化wordpress 列表页输出
  • 在线网站编辑前端个人介绍网站模板下载
  • 网做网站方案解决网站
  • 南京网站推广价格设计型网站
  • 做书app下载网站有哪些怎么网站推广
  • 做微商在哪个网站打广告好黑龙江住房和建设厅网站
  • 网站建设免费软件宁波关键词优化时间
  • 公共资源交易平台官网洛阳seo
  • 杭州响应式网站开发手机微信登入网站
  • 如何自建网站做淘客上海企业服务云app