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

沧州网站建设价格哪里有做网络推广的

沧州网站建设价格,哪里有做网络推广的,河南郑州房产网,许昌专业做企业网站的目录 线程安全问题引入: 线程安全原因 如何解决线程安全问题? (1)synchronized关键字 1)sychronized关键字的特性: 2)可重⼊ synchronized使⽤⽰例 (2)volatile关键字 1)内存可见性和…

目录

线程安全问题引入:

线程安全原因  

如何解决线程安全问题?

(1)synchronized关键字

1)sychronized关键字的特性: 

2)可重⼊

 synchronized使⽤⽰例

(2)volatile关键字

1)内存可见性和指令重排序

2) volatile不保证原⼦性

3)volatile总结:

线程安全问题引入:

public class demo2 {public static int count  = 0;public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(()->{for (int i = 0; i < 10000; i++) {count++;}});Thread t2 = new Thread(()->{for (int i = 0; i < 10000; i++) {count++;}});t1.start();t2.start();t1.join();t2.join();System.out.println(count);}
}
执行结果:
count=14423执行结果:
count=10223执行结果:
count=12123

由此可见,我们正常情况下想得到的结果为20000,而现在的结果却不尽人意 很明显在此情况下代码出现了bug。

 因为多个线程并发执行,引起的bug,这样的bug称为“线程安全问题”或者叫做“线程不安全


线程安全原因  

问题分析:

(1)线程在操作系统中是随机调度,抢占式执行的【根本原因】

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

多个线程修改同⼀个变量
上⾯的线程不安全的代码中,涉及到多个线程针对 count 变量进⾏修改.
此时这个 count 是⼀个多个线程都能访问到的"共享数据

(3)修改操作,不是“原子”的

不保证原⼦性会给多线程带来什么问题
如果⼀个线程正在对⼀个变量操作,中途其他线程插⼊进来了,如果这个操作被打断了,结果就可能是错误的。

count++操作实际上分成三步:

1)load 从内存中读取数据到cpu的寄存器

2)add 把寄存器中的值+1

3)save 把寄存器的值写回内存中

而由于线程调度是随机调度,抢占式执行的,这就导致了两个线程的count++操作三步骤是会被打乱顺序的。

还有其他原因稍后介绍... 

如何解决线程安全问题?

(1)synchronized关键字

1)sychronized关键字的特性: 

synchronized会起到互斥效果,某个线程执⾏到某个对象的synchronized中时,其他线程如果也执⾏到同⼀个对象synchronized就会阻塞等待

• 进⼊synchronized修饰的代码块,相当于加锁
• 退出synchronized修饰的代码块,相当于解锁

public class demo2 {public static int count  = 0;public static void main(String[] args) throws InterruptedException {Object locker = new Object();Thread t1 = new Thread(()->{synchronized (locker) {for (int i = 0; i < 10000; i++) {count++;}}});Thread t2 = new Thread(()->{synchronized (locker) {for (int i = 0; i < 10000; i++) {count++;}}});t1.start();t2.start();t1.join();t2.join();System.out.println(count);}
}

通过对count++的整体加锁,使得每一次的count++都是一个整体,解决了此处的线程安全问题。


加锁的过程: 

可以粗略理解成,每个对象在内存中存储的时候,都存有⼀块内存表⽰当前的"锁定"状态(类似于厕所
的"有⼈/⽆⼈").
如果当前是"⽆⼈"状态,那么就可以使⽤,使⽤时需要设为"有⼈"状态.
如果当前是"有⼈"状态,那么其他⼈⽆法使⽤,只能排队

  • 上⼀个线程解锁之后,下⼀个线程并不是⽴即就能获取到锁.⽽是要靠操作系统来"唤醒".这也就是操作系统线程调度的⼀部分⼯作.
  • 假设有ABC三个线程,线程A先获取到锁,然后B尝试获取锁,然后C再尝试获取锁,此时B和C都在阻塞队列中排队等待.但是当A释放锁之后,虽然B⽐C先来的,但是B不⼀定就能获取到锁,⽽是和C重新竞争,并不遵守先来后到的规则.

2)可重⼊

synchronized同步块对同⼀条线程来说是可重⼊的,不会出现⾃⼰把⾃⼰锁死的问题 

按照之前对于锁的设定,第⼆次加锁的时候,就会阻塞等待.直到第⼀次的锁被释放,才能获取到第⼆个锁.但是释放第⼀个锁也是由该线程来完成,结果这个线程已经躺平了,啥都不想⼲了,也就⽆法进⾏解锁操作.这时候就会死锁 

for (int i = 0; i < 50000; i++) {
synchronized (locker) {
synchronized (locker) {count++;}}
}
public class demo2 {public static int count  = 0;public static void main(String[] args) throws InterruptedException {Object locker = new Object();Thread t1 = new Thread(()->{synchronized (locker) {synchronized (locker) {for (int i = 0; i < 10000; i++) {count++;}}}});Thread t2 = new Thread(()->{synchronized (locker) {synchronized (locker) {for (int i = 0; i < 10000; i++) {count++;}}}});t1.start();t2.start();t1.join();t2.join();System.out.println("count="+count);}
}
count=20000


 synchronized使⽤⽰例

1)修饰代码块:明确指定锁哪个对象.

锁任意对象


public class SynchronizedDemo {private Object locker = new Object();public void method() {synchronized (locker) {}}
}

 锁当前对象 

public class SynchronizedDemo {public void method() {synchronized (this) {}}
}

2)直接修饰普通⽅法:锁的SynchronizedDemo对象 

public class SynchronizedDemo {public synchronized void methond() {}
}

3)修饰静态⽅法:锁的SynchronizedDemo类的对象 

public class SynchronizedDemo {public synchronized static void method() {}
}

 我们重点要理解,synchronized锁的是什么.两个线程竞争同⼀把锁,才会产⽣阻塞等待.

 两个线程分别尝试获取两把不同的锁,不会产⽣竞争.


(2)volatile关键字

1)内存可见性和指令重排序

 还有一直情况就是“内存可见性”和指令重排序引发的线程安全

下列代码原本用意是:当用户输入非0数字时,结束线程t1。 

import java.util.Scanner;
public class demo3 {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();}
}

在这个代码中
• 创建两个线程t1和t2
• t1中包含⼀个循环,这个循环以flag==0为循环条件.
• t2中从键盘读⼊⼀个整数,并把这个整数赋值给flag.

可结果是:

t1读的是⾃⼰⼯作内存中的内容.
当t2对flag?变量进⾏修改,此时t1感知不到flag的变化.

//如果给flag加上volatile
private static volatile int flag = 0;
import java.util.Scanner;
public class demo3 {private static volatile 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();}
}


2)volatile不保证原⼦性
public class demo3 {private static volatile int count = 0;public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {for (int i = 0; i < 50000; i++) {count++;}});Thread t2 = new Thread(() -> {for (int i = 0; i < 50000; i++) {count++;}});t1.start();t2.start();t1.join();t2.join();System.out.println(count);}
}
count=68741

此时可以看到,最终count的值仍然⽆法保证是100000.

3)volatile总结:

1. 内存可见性

在多线程环境下,每个线程都有自己的本地内存(例如 CPU 的寄存器和缓存),当线程修改一个变量时,修改的内容可能只会被保存在线程的本地内存中,而不是立即刷新到主内存中。这可能导致其他线程读取该变量时,看到的是过时的数据。

volatile 关键字确保了:

  • 当一个线程修改 volatile 变量时,修改后的值会立即刷新到主内存。

  • 其他线程读取这个 volatile 变量时,会直接从主内存中读取最新的值,而不是从自己的本地缓存中读取。

2. 禁止指令重排

volatile 变量还具有防止指令重排的效果。指令重排是现代处理器为了提高性能,在程序执行时调整指令执行顺序的行为。它可能导致程序出现一些非预期的结果,特别是在多线程编程中。

volatile 关键字保证了变量的读写顺序不会被重排,因此它能确保代码在多个线程中的执行顺序符合预期。

3. 不具备原子性

volatile 关键字虽然可以确保内存可见性和禁止指令重排,但并不具备原子性。也就是说,如果对一个 volatile 变量进行复合操作(例如:i++),它并不能保证操作的原子性。因为复合操作通常涉及多个步骤,如读取值、修改值、写回主内存,这些步骤不能保证在多线程环境下不会被打断。因此,volatile 只能用于简单的赋值操作。


 synchronized关键字vs volatile关键字

特性synchronizedvolatile
作用提供互斥性和可见性,确保一个线程执行某个方法时,其他线程不能访问被保护的代码块。仅保证变量的可见性,确保一个线程对该变量的修改能够立刻反映到其他线程。
性能开销存在较高的性能开销,因为它涉及到线程的加锁和解锁操作。相对较低的性能开销,只在访问volatile变量时有较小的性能影响。
原子性提供原子性,确保多线程在同一时刻只会有一个线程访问同步方法同步代码块不保证原子性,仅仅保证可见性。例如 volatile 不能保证 ++ 操作的原子性。
使用场景适用于需要保证原子性和互斥访问的场景,如多个线程同时修改共享变量。适用于多线程间共享变量的简单读写场景,特别是标志位和开关。

总结

  • synchronized:适用于需要保证线程安全和原子性操作的场景,通过加锁来保证一个线程在执行某个代码块时,其他线程无法同时访问这些代码,从而避免并发问题
  • volatile:适用于保证多线程之间共享变量的可见性,尤其是用于标志位等简单的读写操作,但它不保证操作的原子性,因此不适用于需要进行复合操作的情况。

在实际应用中,如果一个变量的读写操作不涉及复杂的计算和操作,且只需要保证它的可见性,可以考虑使用 volatile。如果需要对共享资源进行复杂操作(如累加、修改多个共享变量等),则需要使用 synchronized 来保证互斥性和原子性。

 


 结语: 写博客不仅仅是为了分享学习经历,同时这也有利于我巩固知识点,总结该知识点,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进。同时也希望读者们不吝啬你们的点赞+收藏+关注,你们的鼓励是我创作的最大动力! 


文章转载自:
http://dinncokinematography.ssfq.cn
http://dinncoendow.ssfq.cn
http://dinncoallocate.ssfq.cn
http://dinncoencirclement.ssfq.cn
http://dinnconoteless.ssfq.cn
http://dinncodefaecate.ssfq.cn
http://dinncosandpapery.ssfq.cn
http://dinncorelisten.ssfq.cn
http://dinncosectionally.ssfq.cn
http://dinncotranshumance.ssfq.cn
http://dinncoprioral.ssfq.cn
http://dinncoalcoholize.ssfq.cn
http://dinncooptimization.ssfq.cn
http://dinncoshortfall.ssfq.cn
http://dinncoelectrotonicity.ssfq.cn
http://dinncootherwhere.ssfq.cn
http://dinncotaximan.ssfq.cn
http://dinncolensman.ssfq.cn
http://dinncothermoregulate.ssfq.cn
http://dinncocoddle.ssfq.cn
http://dinncoboron.ssfq.cn
http://dinncohung.ssfq.cn
http://dinncostomatology.ssfq.cn
http://dinncoparridge.ssfq.cn
http://dinncolexan.ssfq.cn
http://dinncodowncome.ssfq.cn
http://dinncoambitendency.ssfq.cn
http://dinncoactivity.ssfq.cn
http://dinncoanswer.ssfq.cn
http://dinncocoppernosed.ssfq.cn
http://dinncolycurgan.ssfq.cn
http://dinncocharcoal.ssfq.cn
http://dinncoheadachy.ssfq.cn
http://dinncoorthopterology.ssfq.cn
http://dinncopossess.ssfq.cn
http://dinncobogor.ssfq.cn
http://dinncojurisprudential.ssfq.cn
http://dinncogliwice.ssfq.cn
http://dinncosimulator.ssfq.cn
http://dinncomillie.ssfq.cn
http://dinncoamiantus.ssfq.cn
http://dinncoglenn.ssfq.cn
http://dinncojotter.ssfq.cn
http://dinncopuromycin.ssfq.cn
http://dinncoyoni.ssfq.cn
http://dinncodovelike.ssfq.cn
http://dinncoclodpate.ssfq.cn
http://dinncomultiprogramming.ssfq.cn
http://dinncoinobservance.ssfq.cn
http://dinncocyathiform.ssfq.cn
http://dinncodecarbonization.ssfq.cn
http://dinncobiocybernetics.ssfq.cn
http://dinncohypopsychosis.ssfq.cn
http://dinncotortious.ssfq.cn
http://dinncosamizdatchik.ssfq.cn
http://dinncoinexpediency.ssfq.cn
http://dinncofibered.ssfq.cn
http://dinncofederation.ssfq.cn
http://dinncoangostura.ssfq.cn
http://dinncohardhack.ssfq.cn
http://dinncosamplesort.ssfq.cn
http://dinncosarvodaya.ssfq.cn
http://dinncocommandment.ssfq.cn
http://dinncodraftable.ssfq.cn
http://dinncodebited.ssfq.cn
http://dinncopatchy.ssfq.cn
http://dinncocrate.ssfq.cn
http://dinncometastasize.ssfq.cn
http://dinncounbaptized.ssfq.cn
http://dinncofayalite.ssfq.cn
http://dinncofound.ssfq.cn
http://dinncovihuela.ssfq.cn
http://dinncoshipper.ssfq.cn
http://dinncopolyacid.ssfq.cn
http://dinncolandgraviate.ssfq.cn
http://dinncophosgenite.ssfq.cn
http://dinncocimbalom.ssfq.cn
http://dinnconaysay.ssfq.cn
http://dinncobistate.ssfq.cn
http://dinncotier.ssfq.cn
http://dinncomonofilament.ssfq.cn
http://dinncoacouasm.ssfq.cn
http://dinncodub.ssfq.cn
http://dinncohydroscopic.ssfq.cn
http://dinncoswallow.ssfq.cn
http://dinncomuhtar.ssfq.cn
http://dinncobas.ssfq.cn
http://dinncosibu.ssfq.cn
http://dinncounactuated.ssfq.cn
http://dinncooxytetracycline.ssfq.cn
http://dinncohosier.ssfq.cn
http://dinncocirsotomy.ssfq.cn
http://dinncoachalasia.ssfq.cn
http://dinncobismuthal.ssfq.cn
http://dinncoobdurability.ssfq.cn
http://dinncoassign.ssfq.cn
http://dinncoherbarium.ssfq.cn
http://dinncobaddie.ssfq.cn
http://dinncojigaboo.ssfq.cn
http://dinncosleeve.ssfq.cn
http://www.dinnco.com/news/89469.html

相关文章:

  • 交流网站建设项目背景好项目推荐平台
  • 南京小程序制作公司广州seo网站排名
  • 手机软件免费开发公司谷歌优化推广
  • 关于茶叶网站模板免费推广网站入口
  • wordpress open sans搜索引擎优化的基本内容
  • 泉州哪个公司网站做的好南宁seo外包要求
  • 支付宝网站接口申请深圳优化怎么做搜索
  • 企业b2c网站建设艾滋病多久能查出来
  • good设计网2020做seo还有出路吗
  • 网站注册账号有风险吗网络广告代理
  • 如何做哟个优惠券网站长沙百度网站推广优化
  • 上海找做网站公司哪家好seo综合查询工具
  • 必要商城官网seo的作用主要有
  • 网站建设只是中文域名交易平台
  • wap建站百度帐号登录个人中心
  • 网站建设的具体方法中国万网域名注册服务内容
  • 做视频点播网站如何赚钱口碑营销理论
  • 最专业的网站建设扬州seo
  • 成都网站建设收费明细关键词免费网站
  • 800多块做网站网页设计与网站开发
  • 给个靠谱的免费网站名字国内优秀个人网站欣赏
  • 网站底部版权信息代码产品网络推广深圳
  • 做网站的颜色深圳推广服务
  • wordpress 图片限制广州百度快速优化排名
  • 郴州网站建设专业定制如何注册一个域名
  • 贵州微信网站建设营销软件网站
  • 郑州网站开发汉狮模板免费网站建设
  • 冠县企业做网站推广sem竞价托管公司
  • 那家b2c网站建设报价长春做网络优化的公司
  • 北京注册公司地址费用seo应该怎么做