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

云南公司建网站多少钱东莞做个网站

云南公司建网站多少钱,东莞做个网站,网站seo搜索,公司网站属于信息化建设吗目录 线程状态 线程安全 线程不安全 加锁 互斥性 可重入 死锁 死锁的解决方法 Java标准库中线程安全类 内存可见性引起的线程安全问题 等待和通知机制 线程饿死 wait notify 线程状态 就绪#xff1a;线程随时可以去CPU上执行#xff0c;也包含在CPU上执行的…目录 线程状态 线程安全 线程不安全 加锁 互斥性 可重入  死锁 死锁的解决方法  Java标准库中线程安全类 内存可见性引起的线程安全问题 等待和通知机制 线程饿死 wait notify 线程状态 就绪线程随时可以去CPU上执行也包含在CPU上执行的线程 阻塞这个线程暂时不方便去CPU上执行 Java中线程有下面几个状态 1. NEWThread对象创建好了但还没有调用start在系统中创建线程 2. TERMINATEDThread对象仍然存在但是系统内部的线程已经执行完毕了 3. RUNNABLE就绪状态表示这个线程随时可以去CPU上执行或者在CPU上执行的线程 4. TIMED_WAITING指定时间的阻塞到达一定时间后会自动解除阻塞sleep或者带有超时时间的join 5. WAITING不带时间的阻塞死等一定要满足某个条件才能解除阻塞join或者wait 6. BLOCKED由于锁竞争引起的阻塞 ⚠只有处于NEW状态才能start 如果某个进程卡住了也可以使用jconsole来查看线程的状态 线程安全 之前提过引入多线程是为了实现并发编程但是不能仅仅只靠多线程因为这里面的问题和注意事项很多 后面一些其他的编程语言引入了封装层次更高的并发编程模型 erlang: actor模型 go: csp模型 js: 基于定时器/异步 模型 python主要使用基于时间循环模型 线程安全某个代码无论是在单个线程下执行还是在多个线程下执行都不会产生bug 线程不安全 按照常理count 5w5w 10w但是打印结果远低于10w 而且每次打印的结果不同 这里的count其实是由三个CPU指令构成的 1load 从内存读取数据到CPU寄存器 2add 把寄存器中的值 1 3 save 把寄存器的值写回到内存中 如果两个线程并发执行上面的操作因为线程之间调度的顺序是不确定的所以会存在变数 除了上面的还能画出无数种情况。这也是多线程复杂性的缘由每次写多线程代码都要遍历千万种时间线确保每种时间线都没有bug 诶为什么有无数种情况嘞 完全有可能t2执行一次而t1执行了2次/3次/更多次再排列组合就会产生很多种情况了 为什么上面那张图第一和第二种执行结果是对的 t1执行add之后把结果1保存到t1寄存器上save结果把count 0改为1 t1执行add之后把结果2保存到t2寄存器上save结果把count 1改为2 两个线程有各自的上下文(有各自一套寄存器的值)不会相互影响 后面的情况呢 如果程序自增的数目越小count的差异越难看出来。可能导致第一个线程算完了第二个线程还没开始运行。 线程不安全的原因总结 1. 操作系统上的线程“抢占式执行”“随机调度”线程之间的执行顺序不确定根本原因 2. 代码结构。代码中多个线程同时修改同一个变量单线程修改多线程读取同一个变量没问题多线程修改不同变量没问题 所以之前学过的String对象不可变的特性就是线程安全的 3. 上面的多线程操作本身不是原子的。直接原因 count需要多个CPU指令可能一个线程的指令还没执行完就给调度走给其他线程可乘之机 单个CPU指令就是原子的要么执行完要么不执行 可以通过加锁把这多个CPU指令打包成一个整体实现线程间的锁竞争 4. 内存可见性问题 5. 指令重排序问题 加锁 互斥性 加锁具有互斥排他的特性一般采用synchronized关键字调用系统api进行加锁 加锁前需要准备好一个锁对象依托于这个锁对象进行加锁和解锁操作 如果一个线程针对一个对象加锁之后其他线程尝试对这个对象进行加锁操作就会被阻塞锁冲突/锁竞争阻塞到前一个线程释放锁为止 即使指令会被调度但是其他线程也无法插手 加锁VS串行 这里给t1和t2加锁只是让count这个操作串行执行而for循环还是并行执行的。这样的运行效率还是会比t1t2串行执行高的 ⚠不存在锁竞争可能线程不安全的情况 1.一个线程加锁另一个线程不加锁 2.两个线程加的锁对象不同 ⚠关于锁的混淆 class Test{public int count 0;public void add(){synchronized (this){count;}} } public class ThreadDemo20 {public static void main(String[] args) throws InterruptedException {Test t new Test();Thread t1 new Thread(()-{for (int i 0; i 50000; i) {t.add();}});Thread t2 new Thread(()-{for (int i 0; i 50000; i) {t.add();}});t1.start();t2.start();t1.join();t2.join();System.out.println(count: t.count);} } 这段代码执行效果是怎样的this指的是啥 this指向t而两个线程都调用t.add()方法count 所以两个线程存在锁竞争 这里的this也可以替换成Test.class获取Test的类对象实例化后也就是t (.class指的是类对象包含了类的各种信息类名属性访问限定符参数接口等) 还可以这么写之前学过的StringBuilder和StringBuffer就是这么写的可以保障线程安全 在关键方法前加上synchronized 如果synchronized加到static方法上就是给类对象加锁 可重入  问题下面的代码可以运行后打印hello吗  public static void main(String[] args) {Object locker new Object();Thread t new Thread(()-{synchronized (locker){synchronized (locker){System.out.println(hello);}}});t.start();} 常规认为此时第一个locker对象已经处于加锁状态这时候如果再尝试对locker加锁不就会阻塞吗 但是运行完之后发现真能打印hello 关键在于这两次加锁其实是同一个线程再运行的 当前由于是同一个线程此时锁对象就知道了第二次加锁的线程就是持有锁的线程第二次的操作就可以直接放行通过不会出现阻塞 在Java里面用synchronized加锁利用了它的可重入特性 真正的加锁把计数器1说明当前这个对象被加锁一次同时记录线程是谁 即使上述synchronized嵌套10层8层的也不会使解锁操作混乱始终能够保证在正确的时机解锁这里的计数器就是用来识别解锁时机的关键要点 死锁 场景1.一个线程一把锁如果锁是不可重入锁并且一个线程对这把锁加锁两次就会出现死锁 2. 两个线程两把锁。线程1获取到锁A线程2获取到锁B1尝试获取锁B2尝试获取锁A就出现死锁了 public static void main(String[] args) {Object A new Object();Object B new Object();Thread t1 new Thread(()-{synchronized (A){//sleep一下给t2时间能拿到Btry {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//尝试获取B但没有释放Asynchronized (B){System.out.println(t1拿到两把锁);}}});Thread t2 new Thread(()-{synchronized (B){//sleep一下给t1时间能拿到Atry {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//尝试获取A但是没有释放Bsynchronized (A){System.out.println(t2拿到两把锁);}}});t1.start();t2.start();} 这段代码就是一个例子t1和t2谁都不让谁造成了死锁。结果就是什么都打印不了 用jconsole查看线程情况发现在t1线程第17行代码卡住了 t2线程在32行卡住了 3. N个线程M把锁 先来说一个经典的哲学家就餐问题 现在有5个滑稽哲学家每个哲学家就是一个线程围着餐桌吃一碗面条放在他们面前有5只筷子5只筷子相当于5把锁每个哲学家除了吃面还要思考人生 当某个线程拿到锁的时候就会一直持有除非他吃完了主动放下筷子释放锁其他滑稽不能硬抢筷子 由于每个哲学家啥时候吃面啥时候思考人生这件事不确定所以绝大部分情况下这个模型可以正常运行 但是如果所有哲学家都想吃面都先去拿左手的筷子一只筷子哪够啊。等他们再去拿右手的筷子时发现右手的筷子已经被右边的人拿了此时就产生了死锁 死锁的解决方法  产生死锁的四个必要条件 1.互斥使用获取锁的过程是互斥的。一个线程拿到锁另一个线程只能阻塞等待最基本特性 2.不可抢占。一个线程拿到锁之后只能主动解锁不能让别的线程强行把锁抢走最基本特性 3.请求保持。一个线程拿到锁A之后持有A的前提下尝试获取B代码结构 4.循环等待/环路等待代码结构最容易破坏 解决死锁问题核心思路就是破坏上述四个必要条件任意一个 几种方案 1.引入额外的筷子锁 2.去掉一个哲学家线程 3.引入计数器限制最多多少人吃面 4.引入加锁顺序规则 5.银行家算法 实际开发中我们一般采用第4个方案 比如对上面的5个哲学家针对5只筷子进行编号约定每个哲学家获取筷子的时候一定要先获取编号小的筷子后获取编号大的筷子 按照这个逻辑1号滑稽需要先获取1号筷子此时其他人获取1号筷子就会阻塞等待 5号筷子就是空闲的 用这个思路我们可以把上面第2个场景的代码进行修改约定t2获取锁的顺序让t2先获取锁A再获取锁B Thread t2 new Thread(()-{synchronized (A){//sleep一下给t1时间能拿到Atry {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (B){System.out.println(t2拿到两把锁);}}}); Java标准库中线程安全类 上面的几个类自带锁在多线程环境下使用出现问题的概率比较小 内存可见性引起的线程安全问题 如果一个线程写一个线程读是否会有线程安全问题 private 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(()-{System.out.println(输入flag的值);Scanner scanner new Scanner(System.in);flag scanner.nextInt();});t1.start();t2.start();} 这个代码预期只要t2里面输入的不是0就能让t1线程结束 但是最终效果是我们输入一个非0的值的时候t1没有真的结束 我们来分析一下问题所在 这个循环有2条核心指令 1.load读取内存中flag的值到CPU寄存器里 2.拿着寄存器的值和0进行比较条件跳转 执行指令的速度是很快的在用户指令输入前几秒钟循环已经执行了上百亿次 1.每次load操作执行的结果每次都是一样的 2.load操作开销远远超过条件跳转 load执行很多次每次结果都一样而且每次开销巨大这让JVM产生怀疑不知道你这里的load操作是否有必要 JVM很激进直接把load操作优化了(只有前几次进行load操作后面没发现flag有变化直接干掉load干掉之后就不再重读读内存直接使用寄存器之前缓存的值能大幅度提高循环执行速度) 所以这部分代码相当于t2修改了内存但是t1没有看到这个内存的变化就称为内存可见性问题 内存可见性高度依赖编译器的优化具体实现啥时候触发啥时候不触发不清楚 我们暴力一点直接用sleep让t1线程暂停循环暂停的过程中编译器的优化就不会触发进程也就能顺利结束了 还有一种方法Java提供了volatile关键字来强制读取内存使上述的优化被强制关闭确保每次循环条件都会重新从内存中读取数据 这种方法牺牲了速度但是保证了准确性 拓展JMM模型--Java规范文档上的一个概念 等待和通知机制 wait和notify和join用途类似。因为多个线程之间存在随机调度所以这里引入wait和notify是为了能从应用层面上干预到多个不同线程代码的执行顺序。 join等待另一个线程执行完才继续执行 wait等待当另一个线程收到notify通知之后就结束等待不要求另一个线程必须执行完 换句话说在应用程序代码中让后执行的线程主动放弃被调度的机会就可以让先执行的线程先把对应的代码执行完了。 这里的干预指的是不影响系统的调度策略因为内核里调度线程仍然是无序调度。 线程饿死 假设有一台ATM机器有四个老铁要来取钱。 1号牢铁线程进去取钱把ATM一锁后面排队的人就只能等他取完后才能进去。1号进去后发现ATM里面居然没有钱那他就只能出来等运钞车给ATM补钱。 1号牢铁释放了锁其他牢铁就会来竞争这把锁而且1号牢铁也可以参与到锁竞争中。如果好巧不巧又让1号拿到了锁进去了发现没钱又出来再竞争锁。。。。 如此循环其他牢铁线程根本不可能拿到锁进入ATM 补充1号线程一直拿得到锁的情况发生概率还是蛮高的。 1号先拿到了锁处于RUNNABLE状态而其他线程因为锁冲突出现阻塞处于BLOCKED状态。 BLOCKED状态的线程需要系统进行唤醒之后才能参与到锁竞争中唤醒比较慢1号线程不用被唤醒就可以直接参与竞争 这种情况叫做“线程饿死” 那怎么解决线程饿死呢 这里1号牢铁发现自己要执行的逻辑的前提条件不具备ATM里面没钱这时1号牢铁就要放弃参与到锁竞争中进入线程阻塞状态一直等到条件具备了ATM里面又有钱了再去解除阻塞参与到锁竞争中。 这时候就可以用到wait和notify了让1号滑稽看看当前条件(ATM是否有钱)是否满足不满足就wait其他线程如果让条件满足之后再通过notify唤醒1号滑稽 对应的代码 这里的wait做了三件事 1.释放锁 2.进入阻塞等待 3.当其他线程调用notify的时候wait解除阻塞并重写获取到锁 wait public class ThreadDemo1 {public static void main(String[] args) throws InterruptedException {Object object new Object();object.wait();} } 1. 随便拿个对象都可以进行wait 2. 直接调用wait会出现监视器异常 ⚠wait进来要先释放锁释放锁的前提就是能拿到锁而sychronized也叫做监视器锁wait没有放到sychronized里面的话就会出现监视器异常 Object object new Object();synchronized (object){// 调用wait的对象一定要和synchronized中的锁对象是一致的object.wait();} wait解的是object的锁当wait被唤醒后也能重新获取到object锁 代码执行起来在wait这里阻塞了 此时就需要notify来把它唤醒 wait有三个版本 无参数版本的wait是死等一直等到notify通知 带有超时时间的wait当超过预定时间时就停止等待即使没有notify来通知 notify public static void main(String[] args) {Object locker new Object();Thread t1 new Thread(()-{synchronized (locker){System.out.println(t1 wait之前);try {locker.wait();//wait, sleep和1join都可能被interrupt提前唤醒需要放到try-catch里面} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println(t1 wait之后);}});Thread t2 new Thread(()-{try {Thread.sleep(1000);synchronized (locker){//Java约定notify放到synchronized里面System.out.println(t2 notify之前);locker.notify();System.out.println(t2 notify之后);}} catch (InterruptedException e) {throw new RuntimeException(e);}});t1.start();t2.start();} 分析代码 t1线程启动就会调用wait进入阻塞等待t2线程启动就会先sleep到时间再进行notify唤醒t1 注意要把sleep写到synchronized外面否则因为t1和t2执行顺序不确定可能t2先拿到锁t1没执行到waitt2就进行notify了那逻辑上就有问题了 执行过程 1.t1执行起来之后先拿到锁打印t1 wait之前进入wait方法 2.t2执行起来之后先进行sleep这个sleep可以让t1先拿到锁 3.t2 sleep之后由于t1在wait状态锁是释放的。t2就可以拿到锁接下来打印t2 notify之前执行notify操作使t1从1WAITING状态恢复 4.但此时t2还没有释放锁t1暂时无法获取锁出现小小的阻塞 5.t2执行完notify之后继续打印t1 wait之后 ⚠wait和notify要通过同一个对象来联系 object1.wait(); object2.notify(); 此时是无法唤醒的 ⚠notifyAll() 唤醒这个对象上所有等待的线程 ⚠wait和sleep wait提供了一个带有超时时间的版本sleep也能指定时间时间到解除阻塞继续执行 wait和sleep都可以被提前唤醒wait由notify唤醒sleep由interrupt唤醒 使用wait最主要的目标一定是不知道要等多少时间的前提下使用的。而sleep一定要知道要等多少时间才使用
http://www.yingshimen.cn/news/137912/

相关文章:

  • 房地产网站模板库做网站添加支付功能要多少钱
  • pyton 网站开发网址建站
  • 法制建设网站抖音广告推广怎么做
  • 连云港专业网站优化自己做影视网站
  • 上海网站建设安全没网站可以做百度推广吗
  • 网站建设分几个阶段宣传山西的网页设计
  • 室内设计网站官网大全腾讯企点
  • 深圳建设公司网站岳西县建设局网站
  • 如果自己想建设网站该怎么做php通用企业网站源码
  • 宁波网站优化平台培训学校
  • 视频网站开发用什么服务器北京网站建设公司怎么排版
  • 一般做海报的图片跟哪个网站下载做网页的软件h
  • 做刀模网站网站建设php
  • 服装网站建设策划书的基本结构wordpress 2013
  • 好看的网站分享企业网页设计与推广
  • wordpress_子网站重命名广东网页空间分销
  • 网站建站 优化网站建设的基础知识与维护
  • 998元网站建设优化中小企业怎么优化网站
  • 教育培训学校网站建设方案电商网站流程图
  • 一家专门做特卖的网站手机版公司网站建设推广
  • 南通市住房和城乡建设厅网站贵州网站建设维护
  • 做网站需要的素材照片wordpress建站比较
  • 千岛湖网站建设公司网页介绍
  • 网站建设春节放假如何做国际贸易网站
  • 做视频教育网站离石市网站建设公司
  • 上海政务网站建设贵州网站建设吧
  • iis7如何部署网站门户网站建设专业
  • 广东深圳建设工程信息网站做网站写代码怎么样
  • 京东网站的公司地址新昌网站建设
  • 服装租赁 网站 php设计专业新手网站