本文是总结知乎上面的知识点,虽然忘记了具体的链接地址,但是还是非常感谢知乎里面各位大神的分享!
java 中使用 synchronized 是用来 表示该资源或者该方法是不能进行多个线程的共享的,所以当多个线程都在请求该资源的时候,就跟串行是一样的也就是单线程效果一样,但是当不为共享的时候就可以利用并发来大大的提高系统的效率。
1、多线程并不解决软件执行效率和你硬件系统的瓶颈,它只是达到更高效使用你的硬件系统资源。
2、从本质上来说,单核单CPU不存在并行,即使多线程也是串行,多线程不会提高CPU利用率。
3、对于同步块与单线程执行比较,并不存在多少性能差异,如果相比较,同步块的执行效率还要大大低于单线程程序,如果设计差,可能还是灾难级的。因为同步本身就需要占用系统资源和CPU片段,而且每个线程自己也需要占用资源,如果多线程达不到多线程的优势,那么它本身就会降低效率。
例如下载一首歌曲为10M,采用单线程的方式,那么只能从开头到结束,如果中途出现了什么问题,那么它就不能往下执行了,如果使用多线程,例如开辟2个线程,那么每个线程可以下载5M,这就涉及到一个断点下载的问题了,效率肯定比单线程快,如果里面包含synchronized方法,那么第一个线程在进行任务了,突然出现了什么问题,那么我们可以让第二个线程执行任务,相比于单线程来说效率更高
其实设计synchronized的目的是在使用多线程的时候从安全性方面去考虑的,例如在一个方法中修改一个全局变量,如果使用单线程当然是没什么问题的,一个线程进来我就自己一个人修改,也不会影响什么,但是如果在多线程环境中,很多线程同时访问这个方法修改全局变量,那么就可能会出问题了,可能你争我抢(分配到CPU资源)把这个全局变量改的不成样子了,所以考虑安全性,我们使用synchronized,如果有多个线程,表示你们得一个一个排队来,如果我进去方法里面了,那么我就把门给锁上,只有我一个在里面修改全局变量,你们都不能进来,等我处理完成了,我再释放锁,然后让下一个进来修改,这样也就确保了全局变量不会被改的乱七八糟不成样子了,因为很多项目中会有这样的需求,所以我们得根据需求来确定相应的解决方案!!
举个例子来说,你有100份英语卷子,有听力,选择题和作文三部分;每部分做完之后,必须把100份卷子都交上来以后,才能拿下一部分。
一起拿下一部分的动作就叫做同步,
你是拿叫一个同学做,还是叫100个同学做呢?(单线程,还是多线程)
一个进程中如果有多个线程,那么执行多线程中的非同步代码时比一个进程只有一个线程快。如果进程中有多个线程但是每个线程的所有代码都需要同步的话就和进程只有一个线程的效率是相同的。
线程是在进程中的,一个进程可以有多个线程,单个线程不能脱离进程存在。
所以楼主的问题就是单进程中多线程为何优于多进程(每个进程对应一个线程),当同步时,看上去也都是一个线程在执行,但前者的效率将远远高于后者。因为多线程是共享进程中的数据的,共享数据使得线程之间的通信比进程间通信更快更有效。同时,很多时候,线程相对于进程属于轻量级的,更便于创建和销毁。
ArrayList和Vector有什么区别?HashMap和HashTable有什么区别?StringBuilder和StringBuffer有什么区别?这些都是Java面试中常见的基础问题。面对这样的问题,回答是:ArrayList是非线程安全的,Vector是线程安全的;HashMap是非线程安全的,HashTable是线程安全的;StringBuilder是非线程安全的,StringBuffer是线程安全的。
非线程安全是指多线程操作同一个对象可能会出现问题。而线程安全则是多线程操作同一个对象不会有问题。
线程安全必须要使用很多synchronized关键字来同步控制,所以必然会导致性能的降低。
所以在使用的时候,如果是多个线程操作同一个对象,那么使用线程安全的Vector;否则,就使用效率更高的ArrayList。
非线程安全!=不安全
有人在使用过程中有一个不正确的观点:我的程序是多线程的,不能使用ArrayList要使用Vector,这样才安全。
非线程安全并不是多线程环境下就不能使用。注意我上面有说到:多线程操作同一个对象。注意是同一个对象。比如最上面那个模拟,就是在主线程中new的一个ArrayList然后多个线程操作同一个ArrayList对象。
如果是每个线程中new一个ArrayList,而这个ArrayList只在这一个线程中使用,那么肯定是没问题的。
线程安全的实现
线程安全是通过线程同步控制来实现的,也就是synchronized关键字。
------------------------------------------------------同步异步区别--------------------------------------------------------
他们最大的区别:同步需要等待,而异步无需等待。
例子:
普通B/S模式(同步)AJAX技术(异步)
同步:提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干别的事。
异步: 请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕。
说的再通俗易懂点
同步是按顺序执行,执行完一个再执行下一个,需要等待、协调运行。
异步就是彼此独立,在等待某事件的过程中继续做自己的事,不需要等待这一事件完成后再工作。
线程就是异步实现的一个方式。
异步是让调用方法的主线程不需要同步等待另一线程的完成,从而可以让主线程干其它的事情。
异步和多线程并不是一个同等关系,异步是最终目的,多线程只是我们实现异步的一种手段。
异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回而可以做其它的事情。
实现异步可以采用多线程技术或则交给另外的进程来处理。
同步和异步区别:(好处和坏处)
同步可以避免出现死锁,读脏数据的发生。
一般共享某一资源的时候用,如果每个人都有修改权限,同时修改一个文件,有可能使一个人读取另一个人已经删除的内容,就会出错,
同步就会按顺序来修改。
但是,同步需要等待资源访问结束,浪费时间,效率低。
异步则可以提高效率,
现在cpu都是双核,四核,异步处理的话可以同时做多项工作,当然必须保证是可以并发处理的。
但是安全性较低。
其实,异步是目的,而多线程是实现这个目的的方法。异步是说,A发起一个操作后(一般都是比较耗时的操作,如果不耗时的操作就没有必要异步了),可以继续自顾自的处理它自己的事儿,不用干等着这个耗时操作返回
而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。但是往 往由于使用线程编程的简单和符合习惯,所以很多朋友往往会使用线程来执行耗时较长的I/O操作。这样在只有少数几个并发操作的时候还无伤大雅,如果需要处 理大量的并发操作时就不合适了。
异步与多线程,从辩证关系上来看,异步和多线程并不时一个同等关系,异步是目的,多线程只是我们实现异步的一个手段.什么是异步:异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回.实现异步可以采用多线程技术或则交给另外的进程来处理
=========================================================================
线程池的实现方法与线程是不一样的.初始化时在线程池里的线程为0.当进程需要一个线程时,创建一个线程,由此线程执行用户的方法.需要注意的是,此线程执行完后并不立即销毁,而是挂起等待,如果有其他方法需要执行,回唤醒进行处理.只有当它等到40秒(没有官方记录,有可能是其它数字)还没有任务执行时才唤醒自己,并销毁自己,释放资源.当然,如果线程池中的线程不够处理任务时,会再次创建一个新线程进行执行.
异步执行也得执行,不在当前线程执行,当然得去另外一个线程执行。异步通常用系统线程池的线程,通常情况下性能好些。(因为可以多次利用,申请时不需要重新申请一个线程,只需要从池里取就行了。)异步是一种效果,多线程是一种具体技术。可以说,用“多线程”实现“异步”。
异步和多线程是两个不同的概念,不能这样比较.异步请求一般用在IO等耗时操作上,他的好处是函数调用立即返回,相应的工作线程立即返还给系统以供重用。由于系统的线程资源是非常宝贵的,通常有一定的数目限制,如.net默认是25。若使用异步方式,用这些固定数目的线程在固定的时间内就可以服务更多的请求,而如果用同步方式,那么每个请求都自始至终占用这一个线程,服务器可以同时服务的请求数就少了。当异步操作执行完成后,系统会从可用线程中选取一个执行回调程序,这时的这个线程可能是刚开始发出请求的那个线程,也可能是其他的线程,因为系统选取线程是随机的事情,所以不能说绝对不是刚开始的那个线程。多线程是用来并发的执行多个任务。
不过有个问题,异步有时优先级比主线程还高。这个特点和多线程不同。