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

jquery mobile日本seo入门培训班

jquery mobile日本,seo入门培训班,win2012服务器做网站,平台开发软件多线程(四) 在开始讲之前,我们先来回顾回顾前三篇所讲过的内容~ 线程的概念 并发编程,多进程,比较重,频繁创建销毁,开销大 Thread的使用 创建线程 继承Thread实现Runnable继承Thread&#xff…

多线程(四)

在开始讲之前,我们先来回顾回顾前三篇所讲过的内容~

  1. 线程的概念

    并发编程,多进程,比较重,频繁创建销毁,开销大

  2. Thread的使用

    1. 创建线程
      1. 继承Thread
      2. 实现Runnable
      3. 继承Thread(匿名内部类)
      4. 实现Runnable(匿名内部类)
      5. 使用lambda'
    2. Thread中的重要性
    3. 启动线程start
    4. 终止线程isInterrupted() interrupt()=>本质上是让线程快点执行完入口方法
    5. 等待线程join a.join()让调用这个方法的线程等待a线程的结束
    6. 获取线程引用
    7. 休眠线程
  3. 线程状态(方便快速判定当前程序执行的情况)

    1. NEW
    2. TERMINATED
    3. RUNNABLE
    4. TIMED_WAITING
    5. WAITING
    6. BLOCKED
  4. 线程安全

    1. 演示线程不安全的例子:两个线程自增5w次

    2. 原因:

      • 操作系统对于线程的调度是随机的
      • 多个线程同时修改同一个量
      • 修改操作不是原子性的
      • 内存可见性
      • 指令重排序
    3. 解决:加锁 => synchronized

      synchronized修饰的是一个代码块

      同时指定一个锁对象

      进入代码块的时候,对该对象进行加锁

      出了代码块的时候,对该对象进行解锁


      锁对象

      • 锁对象到底用哪个对象是无所谓的,对象是谁不重要;重要的是两线程加锁的对象是否是同一个对象

      • 这里的意义/规则,有且只有一个

        当两个线程同时尝试对一个对象加锁,此时就会出现“锁冲突”/“锁竞争”,一旦竞争出现,一个线程能够拿到锁,继续执行代码;一个线程拿不到锁,就只能阻塞等待,等待前一个线程释放锁之后,他才有机会拿到锁,继续执行~

      • 这样的规则,本质上就是把“并发执行” => “串行执行”,这样就不会出现“穿插”的情况了。


文章目录

  • 多线程(四)
    • synchronized 关键字
      • 互斥
      • 刷新内存
      • 可重入
    • 死锁
      • 死锁的成因

synchronized 关键字

互斥

续上文最后,synchronized除了修饰代码块之外,还可以修饰一个实例方法,或者一个静态方法

class Counter{public int count;synchronized public void increase(){count++;}public void increase2(){synchronized (this) {count++;}}synchronized public static void increase3(){}public static void increase4(){synchronized (Counter.class){}}
}
// synchtonized 使用方法
public class Demo14 {public static void main(String[] args) throws InterruptedException {Counter counter = new Counter();Thread t1 = new Thread(()->{for (int i = 0; i < 50000; i++) {counter.increase();}});Thread t2 = new Thread(()->{for (int i = 0; i < 50000; i++) {counter.increase();}});t1.start();t2.start();t1.join();t2.join();System.out.println(counter.count);}
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


synchronized用的锁是存在Java对象头里的。

何为对象头呢?

Java的一个对象,对应的内存空间中,除了你自己定义的一些属性之外,还有一些自带的属性

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在对象头中,其中就会有属性表示当前对象是否已经加锁了


刷新内存

synchronized的工作过程:

  1. 获得互斥锁

  2. 从主内存拷贝变量的最新副本到工作的内存

  3. 执行代码

  4. 将更改后的共享变量的值刷新到主内存

  5. 释放互斥锁

但是目前刷新内存这一块知识各种说法都有,目前也难以通过实例验证,pass~


可重入

synchronized:重要的特性,可重入的

所谓的可重入锁,指的就是,一个线程连续针对一把锁,加锁两次,不会出现死锁。满足这个需求就是“可重入锁”,反之就是“不可重入锁”。

下面见图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上述的现象,很明显就是一个bug,但是我们在日常开发中,又难以避免出现上述的代码~例如下面这样的案例:

public class Demo15 {private static Object locker = new Object();public static void func1(){synchronized (locker){func2();}}public  static void func2(){func3();}public static void func3(){func4();}public static void func4(){synchronized (locker){}}public static void main(String[] args) {}
}

要解决死锁问题,我们可以将synchronized设计成可重入锁,就可以有效解决上述的死锁问题~

就是让锁记录一下,是哪个线程给它锁住的,后续再加锁的时候,如果加锁线程就是持有锁的线程,就直接加锁成功~

用一个例子来理解:

你向一个哥们表白,我爱你,成功了,他接受你了,也就是你对他加锁成功了,同时他也会记得你就是她的男朋友~

过了几天,你又对他说,宝贝我爱你,这时候的那个哥们当然也不会拒绝,反而会更加基情~

不过要是换成别人,结果肯定就是不一样的(排除绿你的情况~)


这里提出个问题:

synchronized(locker){synchronized(locker){........................}}
  1. 在上述代码中,synchronized是可重入锁,没有因为第二次加锁而死锁,但是当代码执行到 }②,此时锁是否应该释放?

**不能!!!**因为如果释放了锁,很可能就会导致②和①之间的一些代码逻辑无法执行,也就起不到锁保护代码的作用了~

  1. 进一步,如果上述的锁有n层,释放时机该怎么判断?

无论此处有多少层,都是要在最外层才能释放锁~~
引用计数
锁对象中,不光要记录谁拿到了锁,还要记录,锁被加了几次
每加锁一次,计数器就+1.
每解锁一次,计数器就·1.
出了最后一个大括号,恰好就是减成0了,才真正释放锁


死锁

那么上面我们讲解了死锁的一种情况,一个线程针对一把锁,加锁两次。

接下来下面我们继续介绍死锁的情况~

  1. 一个线程针对一把锁,加锁两次,如果是不可重入锁,就会死锁~

    synchronized不会出现,但是隔壁C++的std::mutex就是不可重入锁,就会出现死锁)

  2. 两个线程(t1、t2),两把锁(A、B)(此时无论是不是不可重入锁,都会死锁)

    举个例子:钥匙锁车里,车钥匙锁家里~

    1. t1获取锁A,t2获取锁B
    2. t1尝试获取B,t2尝试获取A

    实例代码

    // 死锁
    public class Demo16 {private static Object locker1 = new Object();private static Object locker2 = new Object();//此处的sleep很重要,要确保 t1 和 t2 都分别拿到一把锁之后,再进行后续动作public static void main(String[] args) {Thread t1 = new Thread(()->{synchronized (locker1){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (locker2){System.out.println("t1 加锁成功");}}});Thread t2 = new Thread(()->{synchronized (locker2){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (locker1){System.out.println("t2 加锁成功");}}});t1.start();t2.start();}
    }
    

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    死锁现象出现

    我们可以在jconsole.exe中看看线程情况~

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    同时也要注意,死锁代码中
    两个synchronized嵌套关系,不是并列关系.
    嵌套关系说明:是在占用一把锁的前提下,获取另一把锁.(则是可能出现死锁)
    并列关系,则是先释放前面的锁,再获取下一把锁.(不会死锁的)

  3. N个线程,M把锁(相当于2的扩充)

    此时这个情况,更加容易出现死锁了。

    下面给出一个经典例子:哲学家就餐问题

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    死锁,是属于比较严重的bug,会直接导致线程卡住,也就无法执行后续的工作了~

    那么我们应该怎么避免死锁?

死锁的成因

那么首先我们要了解死锁的成因:

  1. 互斥使用。(锁的基本特性)

    当线程持有一把锁之后,另一个线程也想获取到锁,那么就需要阻塞等待、

  2. 不可抢占。(锁的基本特性)

    当锁已经被 线程 1 拿到之后,线程 2 只能等 线程 1 主动释放,不可以强行抢过来

  3. 请求保持。(代码结构)

    一个线程尝试获取多把锁。(先拿到 锁1 之后,再尝试获取 锁2 ,获取的时候, 锁1 不会被释放)

    这种也就是典型的吃着碗里的,看着锅里的

    public class Demo16 {private static Object locker1 = new Object();private static Object locker2 = new Object();//此处的sleep很重要,要确保 t1 和 t2 都分别拿到一把锁之后,再进行后续动作public static void main(String[] args) {Thread t1 = new Thread(()->{synchronized (locker1){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (locker2){System.out.println("t1 加锁成功");}}});Thread t2 = new Thread(()->{synchronized (locker2){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (locker1){System.out.println("t2 加锁成功");}}});t1.start();t2.start();}
    }
    
  4. 循环等待 / 环路等待(代码结构)

    等待的依赖关系,形成环了~

    也即是上面那个例子,钥匙锁车里,车钥匙锁家里

实际上,要想出现死锁,也不是个容易事情
因为得把上面4条都占了.
(不幸的是,1和2是锁本身的特性,只要代码中,把3和4占了,死锁就容易出现了)

所以说,解决死锁,核心就是破坏上述必要条件,死锁就形成不了~

针对上述的四种成因,1 2是破坏不了的,因为synchronized自带特性,我们是无法干预 滴~

对于3来说,就是调整代码结构,避免编写“锁嵌套”逻辑

对于4来说,可以约定加锁的顺序,就可以避免循环等待


所以针对上面的哲学家就餐问题,我们可以采取:针对锁进行编号

比如说约定,加多一把锁的时候,先加编号小的锁,后加编号大的锁(所有线程都要遵守这个规则)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这样的话,循环等待就会被解除,死锁也不会出现了~

回到上述我们讲的synchronized关键字
在使用规则上,并不复杂,只要抓住一个原则:两个线程针对同一个对象加锁,就会产生锁竞争.
但是在底层原理上,synchronized还有不少值得讨论的地方.接下来会展开讲讲~


至此,多线程(四)讲解到这,接下来会持续更新,敬请期待~

http://www.mmbaike.com/news/24115.html

相关文章:

  • 网站采集怎么做发表文章的平台有哪些
  • 成都三级分销网站开发什么是seo网站优化
  • 安徽网站设计流程成人短期就业培训班
  • 做搬家广告哪家网站有优推广学院seo教程
  • 山东做网站推广公司品牌
  • 一学一做看视频网站有哪些抖音seo推广外包公司好做吗
  • 做便宜网站优化人员配置
  • 上饶哪里做网站百度seo查询收录查询
  • balsamiq网站制作教程优质外链平台
  • 2017主流网站风格seo教程网
  • 链接平台谷歌排名优化
  • wordpress自助发货系统淘宝seo排名优化软件
  • 国外免费可以做网站的服务器引流最好的推广方法
  • 照明网站设计谷歌seo站内优化
  • 做一的同志小说网站有哪些巩义关键词优化推广
  • 网站平台维护百度文库首页
  • 内江网站建设如何建立一个自己的网站啊
  • 旅游网站开发意义seo优化网站网页教学
  • 怎么开发一个直播app黑帽seo工具
  • 网站建设基本情况介绍新媒体口碑营销案例
  • 商城微网站创建微信管理系统登录
  • 做简历哪个网站比较好图片seo优化是什么意思
  • 富连网网站开发免费网站入口在哪
  • 源码站免费建站模板
  • 手机网站开发升上去谷歌商店下载安装
  • 随州什么公司做网站杭州网站优化服务
  • 网站建设及管理使用情况汇报搜索风云排行榜
  • 矿区网站建设百度代运营
  • 做外贸b2b网站口碑营销案例
  • 如何建设自己的网站免费的网站推广