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

万州房地产网站建设深圳全网推广公司

万州房地产网站建设,深圳全网推广公司,杭州宣传片制作公司,快站是个什么平台目录 Day 6:多线程(4)1. 线程不安全的原因2. 锁3. synchronized Day 6:多线程(4) 前序:针对Day 5结尾的count 多线程的执行,是随机调度抢占式的执行模式,某个线程执行指…

目录

  • Day 6:多线程(4)
    • 1. 线程不安全的原因
    • 2. 锁
    • 3. synchronized

Day 6:多线程(4)

前序:针对Day 5结尾的count++

多线程的执行,是随机调度抢占式的执行模式,某个线程执行指令过程中,当它执行到任何一个指令的时候,都有可能被其他线程把它的CPU抢占走

实际并发执行,由于上述原因以及count++本质是CPU的三个指令,两个线程执行指令的相对顺序就可能会存在多种可能,不同的执行顺序,得到的结果就可能会存在差异

1. 线程不安全的原因

(1)线程在系统中是随即调度的抢占式执行的,这是线程不安全的罪魁祸首万恶之源

(2)当前代码中,多个线程同时修改同一个变量

(3)线程针对变量的修改操作,不是“原子”的,count++这种操作不是原子的,是包含了三个指令

(4)内存可见性问题(后续介绍)

(5)指令重排序(后续介绍)

针对上述原因进行问题解决

  • 原因(1)无法干预,属于内核设计,无法改变

  • 原因(2)是一个切入点,但是在Java中,并不普适,针对特定场景可以使用,例如String是不可变对象

    • 一个线程修改同一个变量(ok)
    • 多个线程读取同一个变量(ok)
    • 多个线程修改不同的变量(ok)

    String为不可变对象:很好的保证线程安全;有稳定的哈希值;方便在常量池中缓存

  • 原因(3)是解决线程安全问题最普适的方案,可以通过一些操作,把“非原子”操作,打包成一个“原子”操作,例如:加锁

    如果某个代码操作,对应到一个CPU指令,就是原子的,对应到多个就不是原子的,每个代码最终变成哪些指令,需要对芯片手册(CPU指令集)要有比较深入的理解

2. 锁

:本质上是操作系统提供的功能,内核提供的功能,同过api给应用程序了,Java(JVM)对于这样的系统api又进行了封装(其他的语言,同样也可以封装/调用这样的系统api来完成加锁操作)

锁的操作主要是两个方面

  • 加锁:t1加锁之后,t2也尝试加锁,就会阻塞等待(系统内核控制的),在Java中就能看到BLOCKED状态
  • 解锁:直到t1解锁之后,t2才有可能拿到锁(加锁成功),体现了锁的互斥

锁的主要特性:互斥,一个线程获取到锁之后,另一个线程也尝试加这个锁,就会阻塞等待,也叫做锁竞争/锁冲突

代码中可以创建多个锁,只有多个线程竞争同一把锁,才会产生互斥,针对不同的锁,则不会

3. synchronized

synchronized (locker){.......
}
  • synchronizedJava中的关键字,指的是同步的,此处谈到的同步,指的是互斥/独占,反义词可以理解为共享
  • synchronized (locker),()里面就是写的“锁对象”
    • 锁对象的用途,有且只有一个,就是用来区分两个线程是否是针对同一个对象加锁,如果是,就会出现锁竞争/锁冲突/锁互斥,就会引起阻塞等待
    • 和对象具体是什么类型,有什么属性或者方法,没有任何关系
  • {}进入到代码块,就是给上述()锁对象进行了加锁操作,当出了代码块,就是给上述()锁对象进行了解锁操作
package thread;public class Demo20 {private static int count = 0;public static void main(String[] args) throws InterruptedException {Object locker = new Object();Thread t1 = new Thread(() ->{for (int i = 0; i < 50000; i++) {synchronized (locker){count++;}}});Thread t2 = new Thread(() ->{for (int i = 0; i < 50000; i++) {synchronized (locker){count++;}}});t1.start();t2.start();t1.join();t2.join();System.out.println("count = " + count);}
}

这两个线程中,每次进行count++是存在锁竞争的,会变成串行执行,但是执行for循环中的条件以及i++,仍然是并发执行的

package thread;class Counter {private int count = 0;//synchronized修饰普通方法,就相当于针对this加锁了public void add() {synchronized (this){count++;}}//上述方法也可以写成如下形式synchronized public void add() {count++;}public int get(){return count;}//synchronized修饰static方法,相当于针对该类的类对象加锁public static void func() {synchronized(Counter.class){//.....}}//上述方法也可以写成如下形式synchronized public static void func(){//......}}
public class Demo20 {public static void main(String[] args) throws InterruptedException {Counter counter = new Counter();Thread t1 = new Thread(() ->{for (int i = 0; i < 50000; i++) {counter.add();//counter.func();}});Thread t2 = new Thread(() ->{for (int i = 0; i < 50000; i++) {counter.add();//counter.func();}});t1.start();t2.start();t1.join();t2.join();System.out.println("count = " + counter.get());}
}

synchronized(Counter.class)中的Counter.class反射,即程序运行时,能够拿到类一些属性信息,包括不限于

  • 类的名字,继承自哪个类,实现了哪些interface
  • 类提供了哪些方法,每个方法叫什么,每个方法有什么参数,参数是什么类型
  • 类提供了哪些属性,每个属性叫什么,每个属性是什么类型(public/private…)

上述信息,最初都是程序员自己写的.java源代码中提供的

  • java编译之后,.java形成了.class字节码,上述信息转化为二进制
  • java运行.class字节码,就会读取这里的内容, 加载到内存中,给后续使用这个类,提供基础
  • 所以JVM中在内存里保存上述信息的对象,就是类对象,后续想创建这个类的实例,就需要依照上述信息
  • 在Java中可以通过类名.class来拿到这个类对象,一个java进程中,某个类,只能有唯一一个类对象

所以,一旦多个线程调用func,则这些线程都会触发锁竞争

http://www.masaee.cn/news/169.html

相关文章:

  • 莱州网站建设教程seo 推广
  • 只做av搬运工的网站b2b免费推广平台
  • 打开一张图片后点击跳转到网站怎么做的淘宝怎么优化关键词步骤
  • 后台网站地图百度seo优化培训
  • 重庆网站推广步骤今天的新闻发布会
  • 建设租房子的网站seo技术交流论坛
  • 网站qq微信分享怎么做的潍坊seo招聘
  • 提升网站流量的方法长春网站优化指导
  • 做魔方网站用什么背景最好如何提高网站在搜索引擎中的排名
  • 512内存服务器做网站微商推广哪家好
  • 做软件项目需不需要有网站鸡西网站seo
  • 焦作做网站公司微信营销
  • 口碑好的常州做网站网站seo优化推广
  • java电商网站开发流程网络推广软文
  • wap网站是什么意思啊万能搜索引擎入口
  • c#网站开发模板杭州最专业的seo公司
  • wordpress网站做appseo关键词推广话术
  • 宁波做网站价格太原seo排名优化公司
  • 武汉市网站互联网营销具体做什么
  • 深圳网站制作联系兴田德润优秀软文营销案例
  • 做电影网站侵权吗上海企业网站seo
  • 网站建设设计企业网站制作费用
  • 外国网站 游戏设定图河北百度seo关键词排名
  • 哪里做网站优化故事性营销软文
  • 丹东做网站的百度网站优化公司
  • 云平台网站优化怎么样做网站推广
  • 做视频网站视频用什么插件吗长沙网络公司最新消息
  • 做百度网站接到多少客户电话电商平台哪个最好最可靠
  • 网站需要公安备案吗酒店营销策划与运营
  • xx汽车企业网站和信息化建设百度首页广告多少钱