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

专业开发网站建设哪家好seo优化销售

专业开发网站建设哪家好,seo优化销售,wordpress教材.txt,四川做网站找谁文章目录并发编程的三大特性1、原子性什么是并发编程的原子性#xff1f;保证并发编程的原子性synchronizedCASLock锁ThreadLocal2、可见性什么是可见性?解决可见性的方式volatilesynchronizedLockfinal3、有序性什么是有序性?as-if-serialhappens-beforevolatile并发编程的… 文章目录并发编程的三大特性1、原子性什么是并发编程的原子性保证并发编程的原子性synchronizedCASLock锁ThreadLocal2、可见性什么是可见性?解决可见性的方式volatilesynchronizedLockfinal3、有序性什么是有序性?as-if-serialhappens-beforevolatile并发编程的三大特性 原子性、可见性、有序性。 1、原子性 什么是并发编程的原子性 JMM(Java Memory Model)。不同的硬件和不同的操作系统在内存上的操作有一定差异的。 Java为了解决相同代码在不同操作系统上出现的各种问题用JMM屏蔽掉各种硬件和操作系统带来的差异。 让Java的并发编程可以做到跨平台。 JMM规定所有变量都会存储在主内存中在操作的时候需要从主内存中复制一份到线程内存(CPU内存)在线程内部做计算。然后再写回主内存中(不一定)。 原子性的定义原子性指一个操作是不可分割的不可中断的一个线程在执行时另一个线程不会影响到他。 并发编程的原子性用代码阐述 private static int count;public static void increment() {try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}count;}public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {for (int i 0; i 100; i) {increment();}});Thread t2 new Thread(() - {for (int i 0; i 100; i) {increment();}});t1.start();t2.start();t1.join();t2.join();System.out.println(count);}当前程序多线程操作共享数据时预期的结果与最终的结果不符。 原子性多线程操作临界资源预期的结果与最终结果一致。 通过对这个程序的分析可以查看出的操作一共分为了三部首先是线程从主内存拿到数据保存到CPU的寄存器中然后在寄存器中进行1操作最终将结果写回到主内存当中。 保证并发编程的原子性 synchronized 因为操作可以从指令中查看到 可以在方法上追加synchronized关键字或者采用同步代码块的形式来保证原子性。 synchronized可以让避免多线程同时操作临街资源同一时间点只会有一个线程正在操作临界资源。 CAS compare and swap也就是比较和交换他是一条CPU的并发原语。 他在替换内存的某个位置的值时首先查看内存中的值与预期值是否一致如果一致执行替换操作。这个操作是一个原子性操作。 Java中基于Unsafe的类提供了对CAS的操作的方法JVM会帮助我们将方法实现CAS汇编指令。 但是要清楚CAS只是比较和交换在获取原值的这个操作上需要你自己实现。 private static AtomicInteger count new AtomicInteger(0);public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {for (int i 0; i 100; i) {count.incrementAndGet();}});Thread t2 new Thread(() - {for (int i 0; i 100; i) {count.incrementAndGet();}});t1.start();t2.start();t1.join();t2.join();System.out.println(count);}Doug Lea在CAS的基础上帮助我们实现了一些原子类其中就包括现在看到的AtomicInteger还有其他很多原子类。 CAS的缺点CAS只能保证对一个变量的操作是原子性的无法实现对多行代码实现原子性。 CAS带来的问题 ABA问题问题如下可以引入版本号的方式来解决ABA的问题。Java中提供了一个类在CAS时针对各个版本追加版本号的操作。 AtomicStampeReference在CAS时不但会判断原值还会比较版本信息。 public static void main(String[] args) {AtomicStampedReferenceString reference new AtomicStampedReference(AAA, 1);String oldValue reference.getReference();int oldVersion reference.getStamp();boolean b reference.compareAndSet(oldValue, B, oldVersion, oldVersion 1);System.out.println(修改1版本的: b);boolean c reference.compareAndSet(B, C, 1, 1 1);System.out.println(修改2版本的: c);}自旋时间过长问题 可以指定CAS一共循环多少次如果超过这个次数直接失败/或者挂起线程。(自旋锁、 自适应自旋锁)可以在CAS一次失败后将这个操作暂存起来后面需要获取结果时将暂存的操作全部执行再返回最后的结果。 ABA问题 线程1从内存位置V中取出A线程2从内存位置V中取出A线程2进行了写操作将B写入内存位置V线程2将A再次写入内存位置V线程1进行CAS操作发现V中仍然是A交换成功 尽管线程1的CAS操作成功但线程1并不知道内存位置V的数据发生过改变。 Lock锁 Lock锁是在JDK1.5由Doug Lea研发的他的性能相比synchronized在JDK1.5的时期性能好了很很多但是在JDK1.6对synchronized优化之后性能相差不大但是如果涉及并发比较多时推荐ReentrantLock锁性能会更好。 private static int count;private static ReentrantLock lock new ReentrantLock();public static void increment() {lock.lock();try {count;try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}} finally {lock.unlock();}}public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {for (int i 0; i 100; i) {increment();}});Thread t2 new Thread(() - {for (int i 0; i 100; i) {increment();}});t1.start();t2.start();t1.join();t2.join();System.out.println(count);}ReentrantLock可以直接对比synchronized在功能上来说都是锁。但是ReentrantLock的功能性相比synchronized更丰富。 ReentrantLock底层是基于AQS实现的有一个基于CAS维护的state变量来实现锁的操作。 ThreadLocal Java中的四种引用类型分别是强软弱虚。 User user new User(); 在 Java 中最常见的就是强引用把一个对象赋给一个引用变量这个引用变量就是一个强引用。当一个对象被强引用变量引用时它始终处于可达状态它是不可能被垃圾回收机制回收的即使该对象以后永远都不会被用到JVM也不会回收。因此强引用是造成 Java 内存泄漏的主要原因之一。 SoftReference 其次是软引用对于只有软引用的对象来说当系统内存足够时它不会被回收当系统内存空间不足时它会被回收。软引用通常用在对内存敏感的程序中作为缓存使用。 然后是弱引用它比软引用的生存期更短对于只有弱引用的对象来说只要垃圾回收机制一运行不管 JVM 的内存空间是否足够总会回收该对象占用的内存。可以解决内存泄漏问题ThreadLocal就是基于弱引用解决内存泄漏的问题。 最后是虚引用它不能单独使用必须和引用队列联合使用。虚引用的主要作用是跟踪对象被垃圾回收的状态。不过在开发中我们用的更多的还是强引用。 ThreadLocal保证原子性的方式是不让多线程去操作临界资源让每个线程去操作属于自己的数据。 static ThreadLocal tl1 new ThreadLocal();static ThreadLocal tl2 new ThreadLocal();public static void main(String[] args) {tl1.set(123);tl2.set(456);Thread t1 new Thread(() - {System.out.println(t1: tl1.get());System.out.println(t1: tl2.get());});t1.start();System.out.println(main: tl1.get());System.out.println(main: tl2.get());}ThreadLocal实现原理 每个Thread中都存储着一个成员变量ThreadLocalMap。ThreadLocal本身不存储数据像是一个工具类基于ThreadLocal去操作ThreadLocalMap。ThreadLocalMap本身就是基于Entry[]实现的因为一个线程可以绑定多个ThreadLocal这样一来可能需要存储多个数据所以采用Entry[]的形式实现。每一个现有都自己独立的ThreadLocalMap再基于ThreadLocal对象本身作为key对value进行存取ThreadLocalMap的key是一个弱引用弱引用的特点是即便有弱引用在GC时也必须被回收。这里是为了在ThreadLocal对象失去引用后如果key的引用是强引用会导致 ThreadLocal对象无法被回收。 ThreadLocal内存泄漏问题 如果ThreadLocal引用丢失key因为弱引用会被GC回收掉如果同时线程还没有被回收就会导致内存泄漏内* * 存中的value无法被回收同时也无法被获取到。 只需要在使用完毕ThreadLocal对象之后及时的调用remove方法移除Entry即可。 2、可见性 什么是可见性? 可见性问题是基于CPU位置出现的CPU处理速度非常快相对CPU来说去主内存获取数据这个 事情太慢了CPU就提供了L1L2L3的三级缓存每次去主内存拿完数据后就会存储到CPU的 三级缓存每次去三级缓存拿数据效率肯定会提升。 这就带来了问题现在CPU都是多核每个线程的工作内存(CPU三级缓存)都是独立的会告知每个线程中做修改时只改自己的工作内存没有及时的同步到主内存导致数据不一致问题。 可见性问题的代码逻辑 private static boolean flag true;public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {while (flag) {// ....}System.out.println(t1线程结束);});t1.start();Thread.sleep(10);flag false;System.out.println(主线程将flag改为false);}解决可见性的方式 volatile volatile是一个关键字用来修饰成员变量。 如果属性被volatile修饰相当于会告诉CPU对当前属性的操作不允许使用CPU的缓存必须去 和主内存操作。 volatile的内存语义 volatile属性被写当写一个volatile变量JMM会将当前线程对应的CPU缓存及时的刷新到主内存中。volatile属性被读当读一个volatile变量JMM会将对应的CPU缓存中的内存设置为无效必须去主内存中重新读取共享变量。 其实加了volatile就是告知CPU对当前属性的读写操作不允许使用CPU缓存加了volatile修饰的 属性会在转为汇编之后追加一个lock的前缀CPU执行这个指令时如果带有lock前缀会做两个事情 将当前处理器缓存行的数据写回到主内存。这个写回的数据在其他的CPU内核的缓存中直接无效。 总结volatile就是让CPU每次操作这个数据时必须立即同步到主内存以及从主内存读取数据。 private volatile static boolean flag true;public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {while (flag) {// ....}System.out.println(t1线程结束);});t1.start();Thread.sleep(10);flag false;System.out.println(主线程将flag改为false);}synchronized synchronized也是可以解决可见性问题的synchronized的内存语义。 如果涉及到了synchronized的同步代码块或者是同步方法获取锁资源之后将内部涉及到的变量从CPU缓存中移除必须去主内存中重新拿数据而且在释放锁之后会立即将CPU缓存中的数据同步到主内存。 private static boolean flag true;public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {while (flag) {synchronized (MiTest.class) {//...}System.out.println(111);}System.out.println(t1线程结束);});t1.start();Thread.sleep(10);flag false;System.out.println(主线程将flag改为false);}Lock Lock锁保证可见性的方式和synchronized完全不同synchronized基于他的内存语义在获取锁和释放锁时对CPU缓存做一个同步到主内存的操作。 Lock锁是基于volatile实现的。Lock锁内部再进行加锁和释放锁时会对一个由volatile修饰的state属性进行加减操作。 如果对volatile修饰的属性进行写操作CPU会执行带有lock前缀的指令CPU会将修改的数据从 CPU缓存立即同步到主内存同时也会将其他的属性也立即同步到主内存中。还会将其他CPU缓存 行中的这个数据设置为无效必须重新从主内存中拉取。 private static boolean flag true;private static Lock lock new ReentrantLock();public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {while (flag) {lock.lock();try {//...} finally {lock.unlock();}}System.out.println(t1线程结束);});t1.start();Thread.sleep(10);flag false;System.out.println(主线程将flag改为false);}final final修饰的属性在运行期间是不允许修改的这样一来就间接的保证了可见性所有多线程读 取final属性值肯定是一样。 final并不是说每次取数据从主内存读取他没有这个必要而且final和volatile是不允许同时修饰一个属性的。 final修饰的内容已经不允许再次被写了而volatile是保证每次读写数据去主内存读取并且volatile 会影响一定的性能就不需要同时修饰。 3、有序性 什么是有序性? 在Java中.java文件中的内容会被编译在执行前需要再次转为CPU可以识别的指令CPU在执行 这些指令时为了提升执行效率在不影响最终结果的前提下(满足一些要求)会对指令进行重排。 指令乱序执行的原因是为了尽可能的发挥CPU的性能。 Java中的程序是乱序执行的。 static int a, b, x, y;public static void main(String[] args) throws InterruptedException {for (int i 0; i Integer.MAX_VALUE; i) {a 0;b 0;x 0;y 0;Thread t1 new Thread(() - {a 1;x b;});Thread t2 new Thread(() - {b 1;y a;});t1.start();t2.start();t1.join();t2.join();if (x 0 y 0) {System.out.println(第 i 次x x ,y y);}}}单例模式由于指令重排序可能会出现问题: 线程可能会拿到没有初始化的对象导致在使用时可能由于内部属性为默认值导致出现一些不必 要的问题。 private static volatile MiTest test;private MiTest() {}public static MiTest getInstance() { // Bif (test null) {synchronized (MiTest.class) {if (test null) {// A , 开辟空间test指向地址初始化test new MiTest();}}}return test;}as-if-serial as-if-serial语义: 不论指定如何重排序需要保证单线程的程序执行结果是不变的。 而且如果存在依赖的关系那么也不可以做指令重排。 // 这种情况肯定不能做指令重排序 int i 0; i; // 这种情况肯定不能做指令重排序 int j 200; j * 100; j 100; // 这里即便出现了指令重排也不可以影响最终的结果20100happens-before 具体规则 单线程happen-before原则在同一个线程中书写在前面的操作happen-before后面的操作。锁的happen-before原则同一个锁的unlock操作happen-before此锁的lock操作。volatile的happen-before原则对一个volatile变量的写操作happen-before对此变量的任意操作。happen-before的传递性原则如果A操作 happen-before B操作B操作happen-before C操作那么A操作happen-before C操作。线程启动的happen-before原则同一个线程的start方法happen-before此线程的其它方法。线程中断的happen-before原则对线程interrupt方法的调用happen-before被中断线程的检测到中断发送的代码。线程终结的happen-before原则线程中的所有操作都happen-before线程的终止检测。对象创建的happen-before原则一个对象的初始化完成先于他的finalize方法调用。 JMM只有在不出现上述8中情况时才不会触发指令重排效果。不需要过分的关注happens-before原则只需要可以写出线程安全的代码就可以了。 volatile 如果需要让程序对某一个属性的操作不出现指令重排除了满足happens-before原则之外还可以基于volatile修饰属性从而对这个属性的操作就不会出现指令重排的问题了。 volatile如何实现的禁止指令重排? 内存屏障概念。将内存屏障看成一条指令。 会在两个操作之间添加上一道指令这个指令就可以避免上下执行的其他指令进行重排序。
http://www.dnsts.com.cn/news/76600.html

相关文章:

  • 九江专业制作网站小程序郑州电力高等专科学校2021录取分数线
  • 网站建设好吗网站怎么做微信接口
  • 专做美容师招聘网站安徽网站seo
  • 网站首页404德州市建设街小学网站首页
  • 网站怎么做中英文交互手工蛋糕网站开发报告
  • 上的网站app网站怎么接广告赚钱
  • 网站建设优化的作用企业163邮箱怎么申请
  • 地方门户网站源码php一键建站
  • 郑州个人网站开发中国产品网免费网站
  • 东莞网站建设制作软件硬件开发文档模板
  • 2015做微网站多少钱杭州工程建设网
  • 做的视频发到哪个网站网站做联盟收入
  • 运用vs2010c 做网站wordpress 帖子付费
  • 做ic的电子网站有哪些wordpress前台显示友链
  • 网站开发背景意义网络营销推广的目的是
  • 单位网站建设的报告福州网站建设fjfzwl
  • 小学英语教师做应用相关网站公司网站建立流程
  • 信息类网站win8扁平化网站
  • 淘宝请人做网站被骗曲靖建设局网站
  • 韩国优秀电商网站wordpress 执行流程
  • 开发网站建设公司网络调查问卷怎么制作
  • 湛江网站建设方案外包用户体验地图用什么软件画
  • 玉树营销网站建设多少钱怎么制作网站卖东西
  • 建立网站专业公司设计官网费用
  • 网站生成器怎么做唐山公司做网站
  • 做药品的电商网站有哪些平面设计做画册用网站
  • 建设网站需要花费多少钱青岛关键词优化报价
  • 做网站只开发手机端可不可以怎么样开始做网站
  • 小馋网站建设书外包加工网是正规的吗
  • 自己做网站 怎么赚钱西安附近网络营销运营公司