怎么做网站内部链接的优化,wordpress 地址调用,做蛋糕的英文网站,wordpress 检测redis1、什么是 Volatile#xff1f; volatile 是一个类型修饰符#xff0c;具有可见性#xff0c;也就是说一旦某个线程修改了该被 volatile 修饰的变量#xff0c;它会保证修改的值会立即被更新到主存#xff0c;当有其他线程需要读取时#xff0c;可以立即获取修改之后的值… 1、什么是 Volatile volatile 是一个类型修饰符具有可见性也就是说一旦某个线程修改了该被 volatile 修饰的变量它会保证修改的值会立即被更新到主存当有其他线程需要读取时可以立即获取修改之后的值。 在 java 中为了加快程序的运行效率对一些变量的操作通常是在该线程的寄存器或是 CPU 缓存上进行的之后才会同步到主存中而加了 volatile 修饰符的变量则是直接读写主存。 [可以搜索了解一下 java 中的内存模型] 看下面一段代码 class ThreadVolatileDemo extends Thread { public boolean flag true; Override public void run() { System.out.println(开始执行子线程....); while (flag) { } System.out.println(线程停止); } public void setRuning(boolean flag) { this.flag flag; }}public class ThreadVolatile { public static void main(String[] args) throws InterruptedException { ThreadVolatileDemo threadVolatileDemo new ThreadVolatileDemo(); threadVolatileDemo.start(); Thread.sleep(3000); threadVolatileDemo.setRuning(false); System.out.println(flag 已经设置成false); Thread.sleep(1000); System.out.println(threadVolatileDemo.flag); }} 运行结果 开始执行子线程....flag 已经设置成falsefalse 已经将结果设置为 fasle 为什么还一直在运行呢。 原因线程之间是不可见的读取的是副本没有及时读取到主内存结果。 解决办法使用 volatile 关键字将解决线程之间可见性, 强制线程每次读取该值的时候都去“主内存”中取值。 2、Volatile 与 Synchronize 的区别 volatile 虽然具有可见性但是并不能保证原子性。性能方面synchronized 关键字是防止多个线程同时执行一段代码就会影响程序执行效率而 volatile 关键字在某些情况下性能要优于synchronized。但是要注意 volatile 关键字是无法替代 synchronized 关键字的因为 volatile 关键字无法保证操作的原子性。上篇以及本篇多次提及原子性借此重新了解一下多线程中的三大特性。 原子性、可见性、有序性。 2.1、什么是原子性 如果有了解过事务的小伙伴这一块就比较好理解了所谓的原子性即一个或多个操作要么全部执行完成要么就都不执行如果只执行了一部分对不起你得撤销已经完成的操作。 举个例子 账户 A 向账户 B 转账 1000 元那么必然包括 2 个操作从账户 A 减去 1000向账户 B 加上 1000这两个操作必须要具备原子性才能保证不出现一些意外的问题发生。 总结所谓的原子性其实就是保证数据一致、线程安全的一部分。 2.2、什么是可见性 当多个线程访问同一个变量时一个线程修改了这个变量的值其他线程就能够立即看到修改的值。 若两个线程在不同的 cpu有个变量 i 线程 1 改变了 i 的值还没有刷新到主存线程 2 又使用了 i那么这个 i 值肯定还是之前的线程 1 对变量的修改线程2 没有看到这就是可见性问题了。 2.3、什么是有序性 即程序执行时按照代码书写的先后顺序执行。在Java内存模型中允许编译器和处理器对指令进行重排序但是重排序过程不会影响到单线程程序的执行却会影响到多线程并发执行的正确性。(本文不对指令重排作介绍但不代表它不重要它是理解 java 并发原理时非常重要的一个概念)。 重排序文章留空后面补充。 3、多线程之间的通讯 什么是多线程之间的通讯 多线程之间通讯其实就是多个线程在操作同一个资源但是操作的动作不同。画图演示 多线程之间的通讯需求 第一个线程写入(input)用户另一个线程读取(out)用户实现读一个写一个操作。 代码实现 共享资源实习类 Res class Res2{ public String userName; public String userSex;}class InputThread extends Thread{ private Res2 mRes; public InputThread(Res2 mRes){ this.mRes mRes; } Override public void run() { int count 0; while (true) { synchronized (mRes){ if (count 0) { mRes.userName 余胜军; mRes.userSex 男; } else { mRes.userName 小紅; mRes.userSex 女; } count (count 1) % 2; } } }}class OutThread extends Thread{ private Res2 mRes; public OutThread(Res2 mRes){ this.mRes mRes; } Override public void run() { while (true){ System.out.println(mRes.userName -- mRes.userSex); } }}public class Demo9 { public static void main(String[] args){ Res2 res new Res2(); InputThread intThrad new InputThread(res); OutThread outThread new OutThread(res); intThrad.start(); outThread.start(); }} 打印结果 ...余胜军--男小紅--女小紅--女余胜军--男小紅--女 在代码中我们用到了 synchronized 关键字解决线程线程安全问题所以实现了正确打印如果不使用 synchronized 的话可能会出现如下打印的脏数据 余胜军--女小紅--女小紅--男余胜军--男小紅--女 wait()、 notify() 方法。 关于该方法的介绍 因为涉及到对象锁他们必须都放在 synchronized 中来使用。wait 必须暂停当前正在执行的线程并释放资源锁让其他线程可以有机会运行。notify/notifyall唤醒锁池中的线程使之运行。了解了 wait、notify 方法后我们来改造一下上边的代码 class Res2{ public String userName; public String userSex; public boolean flag false;/*线程通讯标识*/}class InputThread extends Thread{ private Res2 mRes; public InputThread(Res2 mRes){ this.mRes mRes; } Override public void run() { int count 0; while (true) { synchronized (mRes){ if(mRes.flag){ try { mRes.wait(); }catch (Exception e){ } } if (count 0) { mRes.userName 余胜军; mRes.userSex 男; } else { mRes.userName 小紅; mRes.userSex 女; } count (count 1) % 2; mRes.flag true; mRes.notify(); } } }}class OutThread extends Thread{ private Res2 mRes; public OutThread(Res2 mRes){ this.mRes mRes; } Override public void run() { while (true){ synchronized (mRes){ if(!mRes.flag){ try { mRes.wait(); } catch (Exception e) {} } System.out.println(mRes.userName -- mRes.userSex); mRes.flag false; mRes.notify(); } } }}public class Demo9 { public static void main(String[] args){ Res2 res new Res2(); InputThread intThrad new InputThread(res); OutThread outThread new OutThread(res); intThrad.start(); outThread.start(); }} wait() 与 sleep() 区别 sleep() 方法时属于 Thread 类的而 wait() 方法是属于 Object 类的。 sleep() 方法导致了程序暂停执行指定的时间让出 cpu 给其他线程但是它的监控状态依然保持着当指定的时间到了又会自动恢复运行状态。 在调用 sleep() 方法的过程中线程不会释放对象锁。 而当调用 wait() 方法的时候线程会放弃对象锁进入等待此对象的等待锁定池只有针对此对象调用 notify() 方法后本线程才进入对象锁池准备获取对象锁进入运行状态。 Lock锁显示锁 lock接口提供了与 synchronized 关键字类似的同步功能但需要在使用时需要手动获取锁和释放锁。 代码示例 Lock lock new ReentrantLock();lock.lock();try{ /*可能会出现线程安全的操作*/}finally{ /*一定在finally中释放锁*/ /*也不能把获取锁在try中进行因为有可能在获取锁的时候抛出异常*/ lock.ublock();} Condition用法—Lock中的wait()、notify() Condition 的功能类似于在传统的线程技术中的 Object.wait() 和 Object.notify() 的功能。 代码 Condition condition lock.newCondition();res. condition.await(); 类似waitres. Condition. Signal() 类似notify synchronized 与 lock 的区别 synchronized 重量级lock 轻量级锁synchronized 不可控制lock 可控制。 lock 相对 synchronized 比较灵活。 我创建了一个java相关的公众号用来记录自己的学习之路感兴趣的小伙伴可以关注一下微信公众号哈niceyoo