多线程是对cpu剩余劳动力的压榨,是一种技术。想想web server 需要处理大量并发请求的场景,是你同时给A,B,C...打电话(你的思维在不断切换,如一边给女朋友打电话一边打lol,让你LoL被杀,打电话被骂不用心,造成反应能力比较差)。
异步强调的是非阻塞,是一种编程模式(pattern),主要解决了UI响应被阻塞的问题,可借助线程技术或者硬件本身的计算能力解决。异步就好像去邮局发信一样,你希望把信发到A家,你把信交给邮局工作人员就可以回家了,不用等着A收到再回家,这个就是异步. (原先就是先等A收到信,然后再回家;现在是你直接回家,让邮局区送信)
多线程并行(多核cpu的出现)虽然同样也是对cpu剩余劳动力的压榨,且基于多线程技术,但它强调的是高效完成计算任务,而不是并发数量。你叫来了你爸妈同时给A,B,C...打电话。
分为多线程并发(单核,代表需要抢占cpu)和多线程并行(多核)。
线程和进程: 进程是:一个应用程序(1个进程是一个软件)。JVM就是一个进程。 线程是:一个进程中的执行场景/执行单元。
eg.
对于java程序来说,当在DOS命令窗口中输入:java HelloWorld 回车之后。会先启动JVM,而JVM就是一个进程。
JVM再启动一个主线程调用main方法(main方法就是主线程)。同时再启动一个垃圾回收线程负责看护,回收垃圾。
最起码,现在的java程序中至少有两个线程并发,一个是 垃圾回收线程,一个是 执行main方法的主线程。线程A和线程B,堆内存
和 方法区
内存共享。但是 栈内存
独立,一个线程一个栈。
其实,异步是目的,而多 线程是实现这个目的的方法。异步是说,A发起一个操作后(一般都是比较耗时的操作,如果不耗时的操作 就没有必要异步了),可以继续自顾自的处理它自己的事儿,不用干等着这个耗时操作返回。
.什么是异步:异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回.实现异步可以采用多线程技术或则交给另外的进程来处理。在异步模型中,允许同一时间发生(处理)多个事件。程序调用一个耗时较长的功能(方法)时,它并不会阻塞程序的执行流程,程序会继续往下执行。当功能执行完毕时,程序能够获得执行完毕的消息或能够访问到执行的结果(如果有返回值或需要返回值时)。
多线程是指同时并发或并行执行多个指令(线程)。在单核处理器上,多线程往往会给人程序是在并行执行的错觉。实际上,处理器是通过调度算法在多线程之间进行切换和调度。或者根据外部输入(中断)和线程的优先级的组合来进行线程的切换。在多核处理器上,线程才是真正的并行运行。多个处理器同时执行多个线程,以达到更加高效的处理。
异步调用并不是要减少线程的开销, 它的主要目的是让调用方法的主线程不需要同步等待在这个函数调用上, 从而可以让主线程继续执行它下面的代码.由于不需要我们等待, 我们等于同时做了两件事情. 这个效果跟自己另外启动一个线程来执行等待方式的写操作是一样的.
多线程只是异步编程的一种实现形式。这里的一个例子很好:比如,你和你的朋友决定一起做一顿午餐。“异步”就是你对朋友说:“你去商店买意大利面,回来的时候告诉我一声,然后一起做午餐。在你买意大利面的同时,我去准备番茄酱和饮料。”
而“线程”是:“你烧水,我加热番茄酱。当水烧开了,告诉我,我把意大利放进去。当番茄酱热了,你可以把奶酪添加进去。当两者都完成了,就可以坐下来一起吃晚餐。”在线程的示例中,我们可以看到“When,Do”的事件顺序,而这些顺序代表着每个人(线程)的指令集集合的顺序。
上述示例可以看出,多线程是与具体的执行者相关的,而异步是与任务相关的。多线程是程序设计的逻辑层概念,它是进程中并发运行的一段代码,可以实现线程间的切换执行。
对于具有大量I/O操作和不同计算的大规模应用程序,使用异步多线程有利于充分利用计算资源,并且能够照顾到非阻塞函数。这也是所有操作系统所采用的线程模型。
纯异步场景:即线程A顺序执行的程序中,添加了线程B处理某个任务,线程A优先返回结果,让调用者可以快速拿到结果,不至于线程A耗时过长而出现阻塞,线程B在返回结果后继续执行任务(可能会出现执行失败,而无法直接告知调用者,需要引入补偿机制),不影响结果的返回,即异步处理。
同步”场景:即线程执行的任务具有返回值,并且需要拿到当前的返回值继续进行执行,使用Future作为返回的类型,此时,多线程的异步已经不是异步执行,而是“同步”执行,因为需要等待线程执行的结果。
(52条消息) Java 实现线程安全的三种方式及如何保证线程安全_刘贤松handler的博客-程序员宅基地
(52条消息) Java多线程(超详细!)_一个快乐的野指针~的博客-程序员宅基地
1.编写一个类,直接 继承 java.lang.Thread
,重写 run方法
。
start() 方法的作用是:启动一个分支线程,在JVM中开辟一个新的栈空间,这段代码任务完成之后,瞬间就结束了。
这段代码的任务只是为了开启一个新的栈空间,只要新的栈空间开出来,start()方法就结束了
MyThread2 t = new MyThread2();
2.编写一个类,实现 java.lang.Runnable
接口,实现run方法
。
Thread t = new Thread(new MyRunnable());
3. .......
杀死线程:
均分式调度模型:
平均分配CPU时间片。每个线程占有的CPU时间片时间长度一样。
平均分配,一切平等。有一些编程语言,线程调度模型采用的是这种方式。
抢占式调度模型:
那个线程的优先级比较高,抢到的CPU时间片的概率就高一些/多一些。
java采用的就是抢占式调度模型。
int getPriority() | 获得线程优先级 |
void setPriority(int newPriority) | 设置线程优先级 |
最低优先级1;默认优先级是5;最高优先级10。优先级比较高的获取CPU时间片可能会多一些。(但也不完全是,大概率是多的。)
静态方法:static Thread currentThread() 获取当前线程对象
实例方法: String getName() 获取线程对象名字 void setName(String name) 修改线程对象名字
static void yield() | 让位方法,当前线程暂停,回到就绪状态,让给其它线程。 |
void join() | 将一个线程合并到当前线程中,当前线程受阻塞,当前线程进入阻塞,直到t线程结束。当前线程才可以继续。 |
静态方法:yield()不是阻塞方法。让当前线程让位,让给其它线程使用。
yield()方法的执行会让当前线程从“运行状态”回到“就绪状态”。
注意:在回到就绪之后,有可能还会再次抢到。
一个线程.join(),当前线程会进入”阻塞状态
“。等待加入线程执行完!
一、什么时候
1:多线程并发。
2:有共享数据。
3:共享数据有修改的行为。
满足以上3个条件之后,就会存在线程安全问题。当多线程并发的环境下,有共享数据,并且这个数据还会被修改,此时就存在线程安全问题
可以看到票出现了 0 和 -1,因为在最后票还剩余1张,因此可以通过 if (ticket > 0)语句,线程2、线程1与线程0都通过了if语句,执行到了sleep语句,进行睡眠,然后线程2首先抢到了CPU,卖出了最后一张票,此时已经没有票可以卖了,然而线程1和线程0又继续抢到了CPU,卖出了票,出现了上述问题
二、产生位置
java中3种变量:
实例变量:在堆中。静态变量:在方法区。
局部变量:在栈中。
以上三大变量中:
局部变量永远都不会存在线程安全问题。因为局部变量不共享。(一个线程一个栈。)
实例变量在堆中,堆只有1个。
静态变量在方法区中,方法区只有1个。
堆和方法区都是多线程共享的,所以可能存在线程安全问题。
总结:
局部变量+常量:不会有线程安全问题。
成员变量(实例+静态):可能会有线程安全问题。
三、解决思路
解决思路:线程排队执行。(不能并发)。用排队执行解决线程安全问题。这种机制被称为:线程同步机制。
专业术语叫做:线程同步,实际上就是线程不能并发了,线程必须排队执行。线程同步就是线程排队了,线程排队了就会 牺牲一部分效率 ,
异步编程模型:
线程t1和线程t2,各自执行各自的,t1不管t2,t2不管t1,谁也不需要等谁,这种编程模型叫做:异步编程模型。其实就是:多线程并发(效率较高。)异步就是并发。
同步编程模型:
线程t1和线程t2,在线程t1执行的时候,必须等待t2线程执行结束,或者说在t2线程执行的时候,必须等待t1线程执行结束,两个线程之间发生了等待关系,这就是同步编程模型。效率较低。线程排队执行。 (分为3种解决方法: 同步代码块, 同步方法 ,LOCK 锁)
四、怎么解决线程安全问题:
1.使用同步代码块synchronized ,锁对象
synchronized(线程共享对象){
同步代码块,可能会出现线程安全问题的代码(访问了共享数据的代码);
}
线程 1 和线程1-2 共用一个对象obj(锁),Thread-0单独用一把锁
假设t1先执行了,遇到了synchronized,这个时候自动找“后面共享对象”的对象锁,
找到之后,并占有这把锁,然后执行同步代码块中的程序,在程序执行过程中一直都是
占有这把锁的。直到同步代码块代码结束,这把锁才会释放。
假设t1已经占有这把锁,此时t2也遇到synchronized关键字,也会去占有后面
共享对象的这把锁,结果这把锁被t1占有,t2只能在同步代码块外面等待t1的结束,
直到t1把同步代码块执行结束了,t1会归还这把锁,此时t2终于等到这把锁,然后
t2占有这把锁之后,进入同步代码块执行程序。
这样就达到了线程排队执行。
重中之重:
这个共享对象一定要选好了。这个共享对象一定是你需要排队
执行的这些线程对象所共享的。
2.使用锁方法:
原理感觉和 锁对象差不多,
this:调用该方法的对象
3.lock
由于synchronized是在JVM层面实现的,因此系统可以监控锁的释放与否;而ReentrantLock是使用代码实现的,系统无法自动释放锁,需要在代码中的finally子句中显式释放锁lock.unlock() (因为要保证unlock一定被执行)。另外,在并发量比较小的情况下,使用synchronized是个不错的选择;但是在并发量比较高的情况下,其性能下降会很严重,此时ReentrantLock是个不错的方案。
五、我们以后开发中应该怎么解决线程安全问题?
是一上来就选择线程同步吗?synchronized
不是,synchronized会让程序的执行效率降低,用户体验不好。
系统的用户吞吐量降低。用户体验差。在不得已的情况下再选择线程同步机制。
第一种方案:尽量使用局部变量 代替 “实例变量和静态变量”。
第二种方案:如果必须是实例变量,那么可以考虑创建多个对象,这样实例变量的内存就不共享了。(一个线程对应1个对象,100个线程对应100个对象,对象不共享,就没有数据安全问题了。)
第三种方案:如果不能使用局部变量,对象也不能创建多个,这个时候就只能选择synchronized了。线程同步机制。
---------------------------------------------------------------------------------------------------------------------------------线程死锁:
---------------------------------------------------------------------------------------------------------------------------------
多线程,高并发 项目:(电商秒杀系统,因为涉及到秒杀,所以并发量非常高)
商城大部分都是微服务,涉及到分布式,所以要考虑到分布式的共享session
比如说:商品有没有超卖
优化思路: 1.缓存 2.异步 3.安全用户(真正用户抢不过 用脚本的黄牛)
文章浏览阅读2.4k次,点赞3次,收藏9次。在写qt网口通信的过程中,遇到中文就乱码。解决方法如下:1.接收端处理中文乱码代码如下 QByteArray-> QString 中文乱码解决: #include <QTextCodec>QByteArray data= tcpSocket->readAll(); QTextCodec *tc = QTextCodec::codecForName("GBK"); QString str = tc->toUnicode(data);//str如果是中文则是中文字符_qbytearray中文乱码
文章浏览阅读2.5k次,点赞2次,收藏15次。什么是 DOM?文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式DOM 树文档:一个页面就是一个文档,DOM 中使用 document 表示元素:页面中的所有标签都是元素,DOM 中使用 element 表示节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node._元素事件
文章浏览阅读1.4k次,点赞3次,收藏7次。关于服务的一些基本知识,包括活动对接口的方法调用,接口实现,服务生命周期等知识。_安卓服务
文章浏览阅读7.9k次,点赞5次,收藏8次。小白式数据库连接池使用,看完拿捏数据库连接池。_采用连接池方式连接数据库
文章浏览阅读4.9k次,点赞5次,收藏36次。摘要:本文介绍了C++11中如何开启新线程,并详细讲解了线程的基础同步原语:mutex, lock_guard, unique_lock, condition variable和semaphore等。如何采用async, packaged_task和promise实现future同步机制?怎样处理spurious wakeup?本文以质数判定服务为例为大家分享C++多线程同步措施!1. C++线程和基础同步原语Thread mutex, lock_guard, unique_lock con._c++线程同步
文章浏览阅读3.3k次,点赞4次,收藏9次。STM32 GPIOx通用输入输出I/O端口的BSRR寄存器与BRR功能简述_gpiob->brr
文章浏览阅读590次。IMP-00019: row rejected due to ORACLE error 12899IMP-00003: ORACLE error 12899 encounteredORA-12899: value too large for column "CRM"."BK_ECS_ORDER_INFO_00413"."POSTSCRIPT" (actual: 895, maximum..._row rejected due to oracle
文章浏览阅读918次。目前很多Web的项目在部署的时候会采用Nginx做为前端的反向代理服务器,后端会部署很多业务处理服务器,通常情况下Nginx代理服务器部署的还是比较少,而且其以高效性能著称,几万的并发连接处理速度都不在话下。然而去年的时候,我们的线上系统也采用类似的部署结构,同时由于我们的业务需求,Nginx的部署环境在虚拟机上面,复用了其他虚拟机的整体磁盘,在高IO消耗的场景中,我们发现Nginx的磁盘_nginx tcp转发 硬盘io
文章浏览阅读645次。Activiti 开发环境的搭建非常简单,主要分为 Activiti runtime 的安装以及 Eclipse 开发环境的配置。本文以 Windows 平台为例介绍 Activiti 5.8 版的开发环境的搭建配置过程。Activiti 的运行时程序可以从http://www.activiti.org/download.html 下载,目前最新版本为 5.8。为了配置使用 Activ_antdev activity
文章浏览阅读2.3k次。1. Vuex 是什么?Vuex 是专门为Vue 组件化思想带来的组件间通信问题提供的解决方案,主要解决以下两个问题:多个视图依赖于同一状态 来自不同视图的行为需要变更同一状态2. 核心概念State: 可以简单理解为Vue 维持的全局变量(状态)。 Getter: 获取State 中的状态的方法,可以在取出前对数据进行二次处理。 Mutation: 是改变State 中的状态..._vuex的组件同级通信
文章浏览阅读8.4k次,点赞31次,收藏33次。逆向中常常出现一些加密算法,如果我们能对这些加密算法进行快速识别则会大大减少我们逆向的难度,虽然IDA已有密码分析神器Findcrypt,但掌握手动分析方法能帮助我们应对更多的情况。这篇文章将介绍逆向中常见的单项散列算法和对称加密算法的识别方法。0xFF. 前言在很长一段时间里我经常发现自己面对复杂的加密算法无从下手,可能是因为还没有系统学过密码学吧orz,总之这个问题困扰了我很久。于是最近我花了一些时间来解决自己在密码学这块的薄弱点,写下这篇文章的目的之一也是为了巩固所学知识。加密算法的部分没有_findcrypt3 支持哪些算法
文章浏览阅读5.3k次。smplayerThere are lots of video players out there, but one that we think gets overlooked is SMPlayer. It can do anything other video players can do and even more – like remembering where you left off ..._sm69影视