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

辽阳住房和城乡建设网站东莞自适应网站建设

辽阳住房和城乡建设网站,东莞自适应网站建设,网站建设郑州,wordpress全局阴影1.线程安全的概念 如果多线程环境下代码运行的结果是符合我们预期的#xff0c;即在单线程环境应该的结果#xff0c;则说这个程序是线 程安全的. 为啥会出现线程安全问题? 本质原因: 线程在系统中的调度是无序的/随机的 (抢占式执行). 2.开始说明 先看个线程不安全的例子… 1.线程安全的概念 如果多线程环境下代码运行的结果是符合我们预期的即在单线程环境应该的结果则说这个程序是线 程安全的. 为啥会出现线程安全问题? 本质原因: 线程在系统中的调度是无序的/随机的 (抢占式执行). 2.开始说明 先看个线程不安全的例子: // 线程不安全 class Counter {private int count 100000;private Object locker new Object();public void add() {synchronized (locker) {count;}}public void sub() {count--;}public int get() {return count;} }public class ThreadDemo13 {public static void main(String[] args) throws InterruptedException {Counter counter new Counter();// 搞两个线程, 两个线程分别对这个 counter 自增 5w 次.Thread t1 new Thread(() - {for (int i 0; i 50000; i) {counter.sub();}});Thread t2 new Thread(() - {for (int i 0; i 50000; i) {counter.sub();}});t1.start();t2.start();// 等待两个线程执行结束, 然后看结果.t1.join();t2.join();System.out.println(counter.get());} } 你觉得结果会是10_0000吗? 测试结果: 这个代码,是两个线程针对同一个变量各自自增 5w 次. 预期结果是 10w,实际结果 像是 个随机值 一样.每次的结果还不一样!!! 实际结果和预期结果不相符,就是 bug!!就是由多线程引起的 bug~~ 线程不安全 /线程安全问题! 归根结底,线程安全问题全是因为,线程的无序调度导致了执行顺序不确定,结果就变化了~~ 解释下为啥出现这个情况,其实是和线程的调度随机性密切相关. count 操作,本质上是 三个 cpu 指令构成 : 1.load,把内存中的数据读取到 cpu 寄存器中 2.add,就是把寄存器中的值,进行 1 运算 3.save,把寄存器中的值写回到 内存中 由于 多线程 调度顺序是不确定的实际执行过程中,这俩线程的 操作实际的指令排列顺序就有很多可能!!!不同的排列顺序下,执行结果,可能是截然不同的!! 此时就发现,按照上述执行过程两个线程自增两次,最后结果是 1,说明 bug 就出现了,其中一次自增的结果,被另一次给覆盖了!!! 由于当前这俩线程调度顺序是无序的,你也不知道这俩线程自增过程中,到底经历了啥.有多少次是“顺序执行”有多少次是“交错执行”不知道!!!得到的结果是啥也就是变化的了~~ 线程不安全有以下原因: 1) 线程抢占式执行 2)多个线程修改同一个变量 3) 修改操作不是原子的 4)由于内存可见性,引起的线程不安全 5) 由于指令重排序,引起的线程不安全 其中123比较常见,也是与上述count例子相关;但是34会在另外的场景涉及,但是和上述count的例子无瓜.下面会说明. 解释一下1)2)3): 1):由于cpu对于线程的调度是无序的,这也就导致了线程会抢占式执行.这也是会导致线程不安全的最主要原因. 2) :多个线程修改同一个变量 是线程不安全的 换言之,一个线程修改/读取同一个变量 是线程安全的. 多个线程修改不同变量 是线程安全的 多个线程读取同一个变量 是线程安全的. 3):如何理解原子性? 表示不可拆分的最小单位. 比如说,一条 java 语句不一定是原子的,换言之,一条Java语句不一定只是由一条指令构成,而是由多条语句构成如上述count操作,其实是由3条指会构成:load,add,save.也正因为语句可能不是原子性的,这也就导致了两个线程在抢占式执行的时候,所执行的指令是不符预期的,也就可能会导致不可预期的结果. 那针对上述count操作所引起的线程不安全问题,能否解决呢? 当然有,那就是让count操作变成原子的. Java中使用synchronize关键字进行加锁操作synchronized 会起到互斥效果某个线程执行到某个对象的 synchronized 中时其他线程如果也执行到同一个对象 synchronized 就会阻塞等待. 举个栗子: 但是,为了保证线程安全,为了实现原子性,就得利用锁竞争,也就必须得保证:多个线程是对同一个对象进行加锁. 在上述代码中,这俩线程是在竞争同一个锁对象()counter对象)! 此时就会产生 锁竞争(t1 拿到锁, t2 就得阻塞)此时就可以保证 操作就是原子的,不受影响了!! 由于 t1 已经率先 lock 了t2 再尝试进行 lock就会出现阻塞等待的情况!!此时就可以保证 t2的 load 一定在 t1的 save 之后此时计算的结果就是线程安全的了!!加锁本质上是把并发的变成了串行的!! synchronize的工作原理以及如何使用synchronize进行加锁: synchronized 的工作过程:1.获得互斥锁 2.从主内存拷贝变量的最新副本到工作的内存 3.执行代码 4.将更改后的共享变量的值刷新到主内存 5.释放互斥锁 如何使用synchronize进行加锁synchronized 要搭配一个具体的对象来使用. 只不过大家要牢记:如果多个线程尝试对同一个锁对象加锁此时就会产生锁竞争针对不同对象加锁,就不会有锁竞争~ 由于内存可见性而引起线程不安全: 先看看场景: public class ThreadDemo14 {volatile public static int flag 0;public static void main(String[] args) {Thread t1 new Thread(() - {while (flag 0) {// 空着}System.out.println(循环结束! t1 结束!);});Thread t2 new Thread(() - {Scanner scanner new Scanner(System.in);System.out.println(请输入一个整数: );flag scanner.nextInt();});t1.start();t2.start();} } 预期效果:t1 通过 flag 0 作为条件进行循环初始情况,将进入循环. 实际效果:输入 非 0的值之后,t1 线程并没有退出.循环没有结束,通过 iconsole 可以看到 t1 线程仍然在执行,处在 RUNNABLE 状态. 为啥有这个问题? 首先需要了解一下内存可见性是个啥内存可见性: 一个线程对共享变量值的修改能够及时地被其他线程看到. 由于 CPU 与内存之间加入了缓存在进行数据操作时先将数据从内存拷贝到缓存中CPU 直接操作的是缓存中的数据。但在多处理器下将可能导致各自的缓存数据不一致(这也是可见性问题的由来). 为此,加上volatile关键字进行修饰,就可以保证各个处理器的缓存是一致的. 为什么会不一致呢?这就涉及到了寄存器和缓存了当重复读一个数据的时候,cpu为了提高效率,只会在第一次从内存中读取数据,此后会把数据加载到寄存器里,以后就直接从寄存器里读取数据,就不会再从内存里读取数据了,可是如果此时其他线程对该数据进行修改了,当前线程由于使用直接复用寄存器的值的方式所以感知不到该值已经被修改了.所以对于当前线程而言,此时该cpu向寄存器里读取到的仍然是旧值,也就是无效值.因此导致线程不安全. 此处咱们的处理方式,就是让编译器针对这个场景暂停优化!! 使用volatile关键字,使编译器停止上述优化volatile强制读写内存, 这也就保证了在各个线程里,cpu在向寄存器读取值的时候,都会重新到内存里进行读取,而不会直接复用寄存器里的旧值.同样,在各个线程里,在对某个数据进行修改时都一定会将修改后的值写回内存,而不会存在仅在自己的工作内存里进行值的修改而不会修改主内存里的值”的情况 具体做法: volatile public static int flag 0 ; 加上 volatile 关键字之后,此时编译器就能够保证每次都是重新从内存读取 flag 变量的值. 此时 t2 修改 flag,t1 就可以立即感知到了.t1 就可以正确退出了!!! 由于指令重排序而导致的线程不安全: 指令重排序,也是编译器优化的策略!调整了代码执行的顺序, 让程序更高效!前提也是保证整体逻辑不变! 谈到优化,都得保证 调整之后的结果 和之前是不变的.单线程下容易保证.如果是多线程,就不好说了! 如果是单线程环境此处就可以进行指令重排序:1 肯定是先执行2 和 3,谁先执行,谁后执行,都可以!! 如果是多线程环境下:假设 t1 按照 1 3 2 的顺序执行,当 t1 执行完 13 之后,即将执行 2 的时候,t2 开始执行.由于 t1 的3 已经执行过了这个引用已经非空了!!!t2 就尝试调用 s.learn0,可是t1还没有该对象进行初始化此时的 learn 会成啥样,不知道了,很可能产生 bug !! 3.总结 volatile:1)为了保证内存可见性,volatile强制读写内存,保证每次都是从内存中重新读取数据. 2)为了解决在多线程的某些场景下,编译器对代码重排序而导致优化后的程序执行结果和之前不等价的问题,volatile禁止指今重排序,保证该场景下的某个逻辑按照”本来的指令顺序”执行. 这里再说一下volatile和synchronize 的区别: 共性:volatile与synchronized都用于保证多线程中数据的安全. 区别:(1) volatie通过强制读写内存和禁止指令重排序来保证线程安全。synchronized则是通过对代码块里的语句进行加锁实现同一时刻只有一个线程能够访问被锁在代码块里的语句,来保证线程安全. (2) volatile仅能用在变量级别;而synchronized可用在变量和多条语句中. (3)volatie仅能实现变量操作的内存可见性无法保证变量操作的原子性;而synchronized可以实现变量操作的内存可见性与原子性. volatile 属性的读写操作都是无锁的它不能替代 synchronized因为它没有无法保证原子性.因为无锁不需要花费时间在获取锁和释放锁上也不会导致线程阻塞,所以volatile比synchronize更轻量. uu们加油呀!!!
http://www.dnsts.com.cn/news/77807.html

相关文章:

  • 电商平台网站开发过程太仓苏州网站建设
  • 建设银行温州分行网站wordpress,视频直播
  • 深圳网站建设兼职中国科技公司100强
  • 宁波建站平台网站怎么被收录
  • 济南网站建设q.479185700惠怎么做网站弹窗通知
  • 制作网站需要怎么做的aspx网站html静态化怎么做
  • php网站开发技术环境要求四川企业网站开发
  • 分类信息网站模板南昌企业建站
  • 游戏网站平台怎么做免费建站免费推广的网站
  • 做英文网站有用吗网站域名销售
  • 网新网站建设合同青岛房产网房天下
  • 缤纷销客crm网站优化策划方案
  • 邯郸网站seo石家庄微信小程序定制
  • 荆州市建设厅网站提供商城网站
  • 网站建设柚子网络科技联系方式合肥seo服务商
  • 山西教育学会网站建设网站设计论文引言
  • wordpress主题演示站网站建设的内容要怎么写
  • 小型购物网站网站建设现在好做吗
  • 中国建设注册中心网站德清县建设局网站
  • 沈阳专业网站制作公司上海工作单位名称大全
  • 网络营销的网站wordpress 响应式模版
  • 中交路桥建设有限公司网站wordpress不好
  • 企业网站开发用什么个人免费建网站
  • 做图赚钱的网站有哪些网站加搜索框
  • 义乌网站设计seo研究中心
  • 怎么看别人网站是什么语言做的成都设计公司工装
  • 如何做网站粘贴广告百度广告投放
  • 动易网络 官方网站代做预算网站
  • 代码素材网站wordpress种子视频
  • 网站的营销与推广如何做网页赚钱