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

免费信息推广网站wordpress中文标题

免费信息推广网站,wordpress中文标题,北京市建设工程信息网如何登录,北京大兴区网站建设3. 线程安全 线程安全#xff1a;某个代码#xff0c;不管它是单个线程执行#xff0c;还是多个线程执行#xff0c;都不会产生bug#xff0c;这个情况就成为“线程安全”。 线程不安全#xff1a;某个代码#xff0c;它单个线程执行#xff0c;不会产生bug#xff0c…3. 线程安全 线程安全某个代码不管它是单个线程执行还是多个线程执行都不会产生bug这个情况就成为“线程安全”。 线程不安全某个代码它单个线程执行不会产生bug但是多个线程执行就会产生bug这个情况就成为 “线程不安全”或者 “存在线程安全问题”。      举个线程不安全例子,我们计算一个变量的自增次数它循环了100000次用两个线程去计算各自计算循环50000次的次数。    3.1 线程不安全样例 根本原因线程的随机调度抢占式执行 代码结构不同线程修改同一数据 直接原因多线程操作不是原子的 由于线程的随机调度抢占式执行不可避免代码结构会促进该原因加剧不良后果 1、代码一分析----代码随机调度抢占执行的例子         代码如下 public class ThreadDemo4 {private static int count 0;public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {for (int i 1; i 50000; i) {count;}});Thread t2 new Thread(() - {for (int i 50000; i 100000; i) {count;}});t1.start();t2.start();t1.join();t2.join();System.out.println(count: count);} }         按照我们的逻辑从1自增到10_0000肯定是自增了10_0000次但是结果如下图所示                我们实际答案却不是10_0000是53978次其出现如上情况的最主原因就是多线程代码它们是并发执行的且往代码深层次分析java中的count语句是由cpu的三个指令构成的 1首先load 从内存中读取数据到cpu的寄存器中 2其次add 把寄存器中的值 1 3最后save 把寄存器中的值写回到内存中         因为上面两个线程t1和t2是并发执行的那则t1 和 t2 线程的执行顺序就是无序的他们可能同时读取内存中的数据add双方都自增完往寄存器1应该是1后再1但是最后从寄存器中save到内存中时却只读取了一个线程自增完后的数值另外一个自增的过程被忽略了一些具体的分析如下图所示         线程并发执行的结果是无数的并不是简单的排列组合就能穷举出来因为并发的原因可能 t1 线程它执行了两次才执行一次 t2 线程或者 t2 执行的次数更多t1 线程只执行一次。等以上这些情况都是有可能出现的。         故此t1 和 t2自增的时候就可能从寄存器中拿的是同一个值这两线程的其中一个自增后没有来得及在内存中进行自加1另一个线程自增完后就直接往内存中那这个值了最后的结果肯定是不符合我们预期的。         故此由上图所示符合我们预期的效果就只有最前面的两个情况了但是这种情况也就是多线程串行化执行执行完 t1再执行t2代码如下所示 public class ThreadDemo4 {private static int count 0;public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {for (int i 1; i 50000; i) {count;}});Thread t2 new Thread(() - {try {t1.join();} catch (InterruptedException e) {throw new RuntimeException(e);}for (int i 50000; i 100000; i) {count;}});t1.start();t2.start();t2.join();System.out.println(count: count);} }         结果如下                但是如此操作的话这个代码和多线程的运行就完全没有关系了                 2、代码二分析----内存可见性例子         代码如下 package thread;import java.util.Scanner;public class ThreadDemo22 {private static int flag 1;public static void main(String[] args) {Thread t1 new Thread(() - {while (flag 1) {System.out.println(这里是线程t1);}System.out.println(t1线程结束);});Thread t2 new Thread(() - {System.out.println(请输入flag的值);Scanner scanner new Scanner(System.in);flag scanner.nextInt();});t1.start();t2.start();} }         执行预期是当我们输入不等于1的值就打印 “t1线程结束”但是当我们输入结果为5最终执行结果却不是我们预期的效果执行结果如下                  flag值是1但是t1线程一直在循环运行虽然t2线程是在按照我们的要求改变flag的值为什么结果与预期是相悖的如此就涉及到了jvm内部的优化了和内存可见性相关         t1线程中的flag1这一操作有两个核心指令 1load读取内存中的flag值到寄存器 2拿着寄存器中的值和1进行比较条件跳转指令         这里load的每次操作取到的值都是一样的而当我们执行scanner操作修改flag的值时load这一指令已经执行上百亿次了且从内存中取数据这一操作是非常耗时的远远比条件跳转指令花时间这时由于load开销太大jvm就会产生怀疑怀疑这个load继续操作的必要性从而给出优化把从内存读数据load这一操作给优化掉了这样一来jvm就不会再从内存中拿数据而是把load拿到的值放到寄存器中从寄存器拿到数据进行比较。这样可以大幅度的提高循环的执行速度。         上面的例子t2修改了内存但是t1没看到内存变化就称为内存可见性问题。而内存可见性问题是高度依赖编译器优化的问题 3.2 线程不安全问题解决方法 3.2.1  t1 循环里加sleep 代码如下 public class ThreadDemo3 {private static int flag 1;public static void main(String[] args) {Thread t1 new Thread(() - {while (flag 1) {try {Thread.sleep(10);} catch (InterruptedException e) {throw new RuntimeException(e);}//循环题里啥也不写}System.out.println(t1线程结束);});Thread t2 new Thread(() - {System.out.println(请输入flag的值);Scanner scanner new Scanner(System.in);flag scanner.nextInt();});t1.start();t2.start();} }         结果如下         方法详解因为10秒中都可以让t1线程里面的循环执行上百亿次cpu飞快的从内存中网寄存器中读取数据这样会导致load的开销就非常大代码的优化迫切程度就比较大但是加了sleep后我们让线程t1进行休眠如此load的开销就小了很多代码的优化迫切程度就降低了故此load就能将5这个值在优化前读取到寄存器和flag进行比较最终达到我们预期的效果 3.3.2 给flag变量加volatile修饰  代码如下 public class ThreadDemo3 {private volatile static int flag 1;public static void main(String[] args) {Thread t1 new Thread(() - {while (flag 1) {//循环题里啥也不写}System.out.println(t1线程结束);});Thread t2 new Thread(() - {System.out.println(请输入flag的值);Scanner scanner new Scanner(System.in);flag scanner.nextInt();});t1.start();t2.start();} }         结果与之前类似略         方法分析 1、java提供volatile关键字其核心作用就是保证 “内存可见性”另一功能禁止指令重排序可以使jvm强迫的优化强制关闭这样就可以确保循环每次都是从内存中拿数据了虽然这样执行效率也会下降但数据更为准确了 2、我们对编译器优化是这样表述的         编译器发现每次循环都要从内存中读取数据内存开销都太大了于是把读取内存这一操作优化成读取寄存器这一操作。         在JMM模型是这样描述的         编译器发现每次循环都要从 “主内存” 中读取数据就会把数据从 “主内存” 中复制下到 “工作内存” 中后续每次读取都是在 “工作内容” 这读取。这里的“工作内容代指cpu寄存器 缓存”----这里的 “主内存” 翻译成内存“工作内存” 翻译成cpu寄存器 3.3 线程不安全的原因 1、根本原因         操作系统上的线程是“抢占式执行”随机调度的----给线程之间的执行顺序带来了很多变数。 2、代码结构         多个线程同时修改同一个变量。     2.1、如果一个线程修改一个变量没事。     2.2、多个线程读取同一个变量没事的--如果只是读取变量的内容是固定不变的。     2.3、多个线程修改不同的变量没事---如果是两个不同的变量彼此之间就不会产生相互覆盖的情况了 3、直接原因         多线程修改操作本身不是原子的         即count该操作可以被细分为3个cpu指令,一个线程执行这些指令执行到一半会被调走从而给其他线程“可乘之机”------每个cpu指令都是原子的要么不执行要么执行完 4、内存可见性         一个线程读一个线程写也会导致线程安全的问题。 5、指令重排序         编译器的一种优化在保证代码逻辑不变的情况下将一些代码的指令重新排序从而提高代码的执行效率但是有时候会因为重排序后多线程编程就会出现线程安全问题。 番外         String是一个不可变对象 好处 方便jvm进行缓存放到字符串常量池中Hash值固定String的对象是线程安全的-à意味着只能读取不能修改 为什么说string是不可变的 持有的数据char 【】数组是private的里面没有提供public的方法来修改char数组的相关内容。Final只是表示不可被继承和可变没有关系。 3.4  针对上述原因给出的解决方案  针对原因1         我们无法给出解决方案因为操作系统内部已经实现了“抢占式执行”我们干预不了 针对原因2         分情况有的时候代码结构可以调整有的时候调整不了。 针对原因3         把要修改的变量这操作通过特殊手段把这操作在系统里的多个指令打包成一个“整体”。例如加锁操作而加锁的操作下一篇详细讲解就是把多个指令打包成一个原子的操作。 针对原因4         可以对代码进行调整避免内存可见性的问题也可以使用volatile进行修饰强制把代码优化关了这样数据就更准确了但执行效率也就变慢了。 针对原因5         将某些可能会指令重排序的变量加volatile修饰强制取消指令重排序的优化。 ps本次的内容就到这里了如果感兴趣的话就请一键三连哦
http://www.w-s-a.com/news/533006/

相关文章:

  • 长沙专业做网站排名游戏开发大亨内购破解版
  • 网站推广适合女生做吗网站如何开启gzip压缩
  • 做外单阿里的网站建站平台那个好
  • 全国性质的网站开发公司关于网站开发的请示
  • 齐齐哈尔住房和城乡建设局网站生物科技公司网站模板
  • 中国建设协会官方网站前端培训的机构
  • 网站建设套餐是什么北京孤儿院做义工网站
  • 网站如何做微信支付链接做暧小视频xo免费网站
  • SEO案例网站建设重庆建站模板平台
  • 上海seo网站推广公司wordpress 小米商城主题
  • 搭建服务器做网站什么网站可以请人做软件
  • 上海建筑建材业网站迁移公家网站模板
  • 仿制别人的网站违法吗网站防火墙怎么做
  • 杨浦网站建设 网站外包公司如何进行网络推广
  • wordpress+仿站步骤超详细wordpress常用函数
  • 浙江手机版建站系统哪个好怎样黑进别人的网站
  • 企业网站搜索引擎推广方法装修网络公司
  • 网站运营优化建议wordpress 添加媒体
  • 用asp.net做网站计数器施工企业会计的内涵
  • 网站被黑咋样的网站建设 设计业务范围
  • 网站开发学哪种语言网站编辑器失效
  • WordPress插件提示信息江阴网站优化
  • 网站开发用的软件如何做网站内容管理
  • 扬州网站建设公司网站推广是什么岗位
  • 双线网站管理咨询公司是做什么
  • asia域名的网站贵州光利达建设工程有限公司局网站
  • 梅州南站济南做网络安全的公司
  • 网站源代码 phpseo营销推广费用
  • 南京专业制作网站深圳整装装修公司排名
  • 网站制作在哪里比较好网页设计的要点有哪些