![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
并发编程学习
文章平均质量分 80
学习java并发基础和实战
程序员小牧之
汲取,分享与成长,我们唯一能做的就是坚持。
展开
-
多线程Demo学习(使用信号量实现线程同步,使用原子变量实现线程同步)
一.使用信号量实现线程同步信号量是Dijkstra在1968年发明,它最初是用来在进程间发信号的一个整数值,一个信号量有且仅有3种操作,且它们全部都是原子操作:初始化,增加和减少。 它的增加可以为一个进程解除阻塞,减少可以让一个进程进入阻塞。 Java为线程提供了信号量支持,本实例将通过向银行存款的例子来实现信号量的同步。我们先运行看一下效果:import java.awt.BorderLayout;import java.awt.EventQueue;import javax.swing.JF原创 2020-12-22 18:21:24 · 412 阅读 · 0 评论 -
多线程Demo学习(哲学家就餐问题)
一.哲学家就餐问题为了快速进入状态我们先来复习下哲学家问题:有5个哲学家去吃中餐,坐在一张圆桌上,他们旁边有五只筷子(每两个人中间放一根),哲学家们时而思考,时而吃饭,但每个人都需要一双筷子才能吃饭,并且在吃完后将筷子放回原处接着思考。这里就有一个问题:我们都知道这五个哲学家不可能同时吃饭,如果他们尝试同时去同时拿筷子,他们每个人只能拿到一个筷子,并且每个人都在等待别人放下手中的筷子,这样他们都会饿死(因为他们都吃不到东西)。 这就是一种死锁。那么怎样才能让五个哲学家都能吃到东西呢? 这就是我们下面原创 2020-12-22 12:17:29 · 323 阅读 · 1 评论 -
多线程Demo学习(使用线程池优化多线程编程,Object线程相关的方法)
一.使用线程池的优势Java中的对象是使用new操作符创建的,如果用new创建大量短生命周期的对象,这种方式性能非常低下。所以为了解决这个问题一些先行者们发明了池技术。 例如对于数据库连接有连接池,一样的对于线程有线程池。 线程池可以极大的简便我们的多线程编程,在需要大量线程的程序编程时,它不仅从编程上简化了,而且性能比new要好。下面我们这个Demo展示了new和线程池方式创建并允许线程的性能:任务类:public class TempThread implements Runnable {//原创 2020-12-21 15:14:22 · 221 阅读 · 0 评论 -
多线程Demo学习(使用阻塞队列实现线程同步,新建有返回值的线程)
一.使用阻塞队列实现线程同步实际开发中使用java.util.concurrent包将有助于简化开发。 本Demo使用其中的LinkedBlockingQueue类来解决生产者消费者问题。首先我们先了解下这个API:LinkedBlockingQueue< E >是一个基于已连接节点的,范围任意的阻塞队列,此队列按照先进先出排序元素。 队列的头部是在队列中时间最长的元素,队列的尾部是在队列中时间最短的元素,新元素插入到队列的尾部。获取队列元素的操作只会获取头部元素,且如果队列满了或者为空会进原创 2020-12-21 14:07:46 · 483 阅读 · 0 评论 -
多线程Demo学习(线程的同步,简单的线程通信)
一.线程的同步我们使用多线程编程的一个重要原因在于方便数据的共享。 但是共享就意味着存在安全性问题:如果两个线程同时修改一个数据,该听谁的?这就引发了同步问题。1.下面我们用一个银行存入的例子来演示多线程编程的非同步的场景:下面一个银行实例类:public class Bank { private int account = 100;// 假设账户的初始金额是100 public void deposit(int money) {// 向账户存钱的方法 accoun原创 2020-12-20 12:37:25 · 533 阅读 · 2 评论 -
多线程Demo学习(使用守护线程,休眠线程,线程插队)
一.使用守护线程在学习本demo之前我们先复习下守护线程的知识:Java中的线程可以分为两类,用户线程和守护线程。 其中用户线程是为了完成任务而存在的,而守护线程是为其他线程服务的,也就是说守护线程存在的意义就是守护其他的非守护线程,只有当所有非守护线程都执行完毕时,守护线程才可以结束。下面的例子中创建两个线程,一个是用户线程,用来输出一些语句。一个是守护线程,用来计算程序的运行时间。工作者任务:public class Worker implements Runnable { public原创 2020-12-19 14:08:25 · 236 阅读 · 3 评论 -
多线程Demo学习(查看和修改线程名称,查看和修改线程优先级,)
1.查看和修改线程名称原创 2020-12-19 13:00:58 · 284 阅读 · 0 评论 -
Java并发学习之并发程序的测试 一
一.概述在编写并发程序时,可以采用与编写串行程序时相同的设计原则与设计模式。 二者的差异在于,并发程序存在一定程度的不确定性,而串行程序中不存在这个问题。所以在测试并发程序时,所面临的主要挑战在于:潜在错误的发生并不具有确定性,而是随机的。 要在测试中将这些故障暴露出来,就需要比普通的串行程序测试覆盖更广的范围并且执行更长的时间。并发测试大致分为两类: 1)安全性测试 2)活跃性测试 。 在前面的学习中我们将安全性定义为:不发生任何错误的行为。 将活跃性定义为:某个良好的行为终究会发生。1.安原创 2020-12-16 13:29:34 · 561 阅读 · 0 评论 -
Java并发之性能和可伸缩性 二
1.检测CPU的利用率当我们测试可伸缩性时,通常要确保处理器得到充分利用。 那我们如何检测CPU的利用率呢?在windows下我们可以通过下面方式来检测,打开cmd:回车。2.在Linux下,我们可以:如果所有的CPU的利用率并不均匀(有些CPU很忙碌,而有些很闲),那么我们的首要目标就是进一步找到程序中的并行性。不均匀的利用率表明大多数计算都是由一小组线程完成的,并且应用程序没有利用其他的处理器。所以说,如果CPU没有得到充分利用,我们就需要找出其中的原因,通常有下面几种原因:1原创 2020-12-14 15:38:32 · 136 阅读 · 0 评论 -
多线程Demo学习(创建线程,查看线程的运行状态,查看线程名)
1.第一个多线程程序public class Text { public static void main(String[] args) { DoThread(); } protected static void DoThread(){ final StringBuilder sb=new StringBuilder(); for(int i=0;i<10;i++){ new Thread(){原创 2020-12-13 21:04:57 · 297 阅读 · 0 评论 -
Java并发之性能和可伸缩性
一.概述线程的最主要的目的就是提高程序的运行性能。 本章将学习各章分析,监测以及提升并发程序性能的技术。但是我们在提升性能的同时要考虑到:程序的安全性才是第一位的。 我们要首先保证我们的程序正确的前提下提升性能。 所以我们需要一些专业的知识去分析如何在不破坏程序的正确性的前提下提升性能。 这也是我们学习本章的目的。二.具体学习1.对性能的思考...原创 2020-12-13 13:21:08 · 382 阅读 · 0 评论 -
Java并发之读写锁
一.概述ReentrantLock 实现了一种标准的互斥锁:每次最多只有一个线程能持有ReentrantLock。但对于维护数据的完整性来说,互斥通常是一种强硬的加锁规则,因此也就不必要的限制了并发性。 互斥是一种保守的加锁策略,虽然互斥可以避免 ”写/写“ 冲突和 “写/读” 冲突,但同样也避免了连带的 “读/读” 冲突(在一些对数据结构的读操作,我们应该允许多个线程同时读取),这时后我们就像如果有一种加锁机制能解决这样的问题就好了,这就是 读写锁。二.具体的学习1.什么是读写锁?一个资源可以原创 2020-12-08 16:57:50 · 190 阅读 · 0 评论 -
Java并发之显式锁
一.概述在Java 5.0之前,在协调对共享对象的访问时可以使用的机制只有synchronized和volatile,我们的选择不多。但在Java5.0 增加了一种新的机制:ReentratLock ,显式锁。 它并不是一种替代内置加锁的方法,而是当内置加锁机制不适用时,作为一种可选择的高级功能。二.具体学习1.Lock与ReentrantLock1)Lock是个接口,其中定义了一组抽象的加锁操作:public interface Lock{ void lock(); void loc原创 2020-12-08 12:31:06 · 153 阅读 · 0 评论 -
Java并发之其他的活跃性危险(饥饿,活锁)
一.概述除了死锁之外,在并发程序中还存在一些其他的活跃性危险,包括:饥饿,活锁等等。下面我们分别了解和学习下。二.具体学习1.饥饿当线程由于无法访问它所需要的资源而不能继续执行时,就会发生 “饥饿(Starvation)” .1)引发饥饿的最常见资源就是CPU时钟周期。如果在java应用程序中对线程的优先级使用不当,或者在持有锁时执行一些无法结束的结构(例如无限循环或者无限制的等待某个资源),那么也可能导致饥饿,因为其他需要这个锁的线程将无法得到它。2)在Thread API 中定义的线程优先原创 2020-12-06 14:39:23 · 150 阅读 · 0 评论 -
Java并发之死锁的避免与诊断
一.概述1.如果一个程序每次至多只能获得 一个锁(这显然不可能出现在实际编程中),那么就不会产生锁顺序死锁。 但是我们可以通过一些策略来避免锁顺序死锁。2.如果必须获取多个锁,那么在设计时必须考虑锁的顺序:尽量减少潜在的加锁交互数量,将获取锁时需要遵循的协议写入正式文档并始终遵循这些协议。3.在使用细粒度锁的程序中,可以通过使用一种两阶段策略(Two-Part Strategy)来检查代码中的死锁:首先,找出在什么地方将获取多个锁(使这个集合尽量小),然后对所有这些实例进行全局分析从而确保他们在整个程原创 2020-12-05 11:22:32 · 196 阅读 · 0 评论 -
Java并发之死锁问题学习
一.避免活跃性危险我们在设计并发程序时,在安全性和活跃性之间通常存在着某种制衡。 我们使用加锁机制来确保线程安全,但如果过度的使用加锁,则可能导致锁顺序死锁(Lock-Ordering Deadlock),同样我们使用线程池和信号量来限制对资源的使用,但这些被限制的行为可能会导致资源死锁(Resource Deadlock)。注意:java应用程序无法从死锁中恢复过来,因此在设计时一定要排除那些可能导致死锁出现的条件。这也就是我们要学习的重点:如何避免一些活跃性问题...原创 2020-12-04 11:48:03 · 260 阅读 · 0 评论 -
Java并发之递归算法并行化
一.递归算法的并行化1.如果在循环中包含了一些密集型计算,或者需要执行可能阻塞的I/O操作,那么只要每次迭代是独立的,都可以对其进行并行化。2.如果循环中的迭代操作都是独立的,并且不需要等待所有迭代操作都完成再继续执行,那么就可以使用Executor将串行循环转化为并行循环。如下://串行循环void processSequentially(List<Element> elements){ for(Element e:elements) process(e);}原创 2020-11-30 10:01:39 · 1272 阅读 · 0 评论 -
Java并发之合理的使用线程池
一.如何设置线程池的大小?有时候我们使用线程池的时候对它的大小的设置没有头绪,下面的学习将对我们在使用线程池的时候如何设置其大小非常有用。首先,线程池的理想大小取决于被提交任务的类型以及所部署系统的特性,在代码中通常不会固定线程池的大小,而应该通过某种配置机制来提供,或者根据Runtime.availableProcessors来动态计算。1.要设置线程池的大小并不困难,只需要避免两种情况:过大 和 过小 这两种极端情况。为什么呢? 如果线程池过大,那么大量的线程将在相对较少的CPU和内存资源上发生原创 2020-11-28 09:37:43 · 203 阅读 · 0 评论 -
Java并发之任务和执行策略之间的隐形耦合
一.一些特殊的任务我们知道Executor框架可以将任务的提交与任务的执行策略解耦开来,虽然Executor框架为制定和修改执行策略都提供了相当大的灵活性,但并非所有任务都能适用于所有的执行策略。1.一些特殊类型的任务需要明确的指定执行策略:1).依赖性任务。 如果提交给线程池的任务需要依赖其他的任务,那么就隐含地给执行策略带来了约束,此时必须小心地维持这些执行策略以避免产生活跃性问题(死锁等问题)。2).使用线程封闭机制的任务。 对象封闭在任务线程中,使得该线程中执行的任务在访问该对象时不需要同原创 2020-11-27 09:41:58 · 267 阅读 · 1 评论 -
java并发学习之JVM关闭
一.JVM关闭当我们创建一个主线程时,JVM都会创建一个JVM实例进程来运行线程,JVM进程既可以正常关闭,也可以强行关闭。正常关闭的触发方式有很多:1)当最后一个“正常(非守护)”线程结束时 。2)调用了System.exit 。3)通过其他特定于平台的方法关闭。强行关闭:我们也可以通过调用Runtime.halt或者操作系统中 “杀死” JVM进程的指令来强行关闭JVM。那么JVM是如何关闭的呢?1.关闭钩子在正常的关闭中,JVM首先调用所有已注册的关闭钩子(Shutdown Hook)。原创 2020-11-26 11:33:33 · 666 阅读 · 0 评论 -
Java并发学习之处理非正常的线程终止
一.如何处理非正常的线程终止我们都知道。当单线程的控制台程序由于发生了一个未捕获的异常而终止时,程序将停止运行,并产生与程序正常输出非常不同的栈追踪信息。但是, 在并发程序中,单个线程的故障很有可能不会影响到整体,而这时的控制台中可能会输出栈追踪信息,但是没人看去看它,就相当于这个异常被忽略!!但是,我们有应对的方法嘿嘿嘿导致线程提前死亡的最主要的原因其实就是RuntimeException. 因为一般的RuntimeException是不可捕获的,它们不会再调用栈中逐层传递,而是默认地在控制台中原创 2020-11-26 09:53:03 · 405 阅读 · 0 评论 -
Java并发学习之停止基于线程的服务
一.停止基于线程的服务1.一般的应用程序中会创建多个线程的服务,例如线程池,我们创建一个线程池的服务时,它会又创建多个线程,如果我们不关闭服务,它会一直存在,所以服务的生命周期通常比创建它们的方法的生命周期更长。如果应用程序准备退出,应用程序会关闭服务,服务又会关闭它拥有的线程。由于无法通过抢占式的方法来停止线程,所以它们需要自行关闭。2.我们对线程的封装原则是:除非拥有某个线程,否则不能对该线程进行操控。线程有一个相应的所有者(创建它的类),因此线程池是其他工作者线程的所有者,如果要中断这些线程,那么原创 2020-11-24 15:28:28 · 183 阅读 · 0 评论 -
Java并发学习之处理不可中断的阻塞
一.不可中断的阻塞1.我们知道在Java库中,许多可阻塞的方法都是通过提前返回或者抛出InterruptedException来响应中断请求的,从而使开发人员更容易构建出能响应取消请求的任务。2.然而,并非所有的可阻塞方法或者阻塞机制都能响应中断。 如果一个线程由于执行同步的Socket I/O或者等待获得内置锁而阻塞,那么中断请求只能设置线程的中断状态,除此之外没有其他任何作用。不对中断请求做出任何响应的阻塞我们称之为不可中断的阻塞。对于那些由于不可中断操作而被阻塞的线程,可以使用类似于中断的手段来原创 2020-11-23 14:49:57 · 650 阅读 · 0 评论 -
Java并发学习之中断策略
一. 中断策略学习我们前面学习了任务包含取消策略,同样的,线程应该包含中断策略。1.中断策略规定线程如何解释某个中断请求:当发现中断请求时,应该做哪些工作(如果需要的话),哪些工作单元对于中断来说是原子操作,以及以多快的速度来响应中断。2.最合理的中断策略是某种形式的线程级取消操作或者服务级取消操作:尽快退出,在必要时清理,通知某个所有者该线程已经退出。3.除此之外还可以建立其他的中断策略:例如暂停服务或者重新开始服务,但对于哪些包含非标准中断策略的线程或线程池,只能用于能知道这些策略的任务中。4原创 2020-11-22 15:37:53 · 378 阅读 · 0 评论 -
Java并发学习之任务取消策略
一.任务取消概述1.我们为什么需要取消任务?任务和线程的启动很容易,在大多数时候,我们都希望它运行直到结束。然而有时候我们需要提前结束任务或线程,原因可能是用户取消了操作,可能是应用程序需要被快速关闭。2.如何取消任务?要使任务和线程能安全,快速,可靠地停下来并不是一件很容易的事情。Java没有提供任何机制来安全地终止线程,但是它提供了中断(Interruption),这是一种协作机制,能够使一个线程终止另一个线程的当前工作。3.协作机制的必要性这种协作机制是非常必要的,我们很少希望某个任务,原创 2020-11-20 14:46:20 · 465 阅读 · 0 评论 -
Java并发学习之为任务设置时限
我们在开发中可能会遇到这种情况:有时候如果某个任务无法在指定时间内完成,那么将不再需要它的结果,此时可以放弃这个任务。例如:某个Web应用程序从外部的广告服务器上获取广告信息,但如果该应用程序在2s中不能得到响应,那么将显示一个默认的广告,类似的,一个门户网站可以从多个数据源并行的获得数据,但可能只会在指定的时间内等待数据,如果超出了等待时间,那么只显示已经得到的数据。1.在有限的时间内执行任务的主要困难在于:要确保得到答案的时间不会超过限定的时间,或者在限定的时间内无法获得答案。我们可以通过Fut原创 2020-11-19 12:05:07 · 494 阅读 · 0 评论 -
Java并发学习之找出可利用的并行性
一.如何找出可利用的并行性Executor框架帮助指定执行策略,但如果要使用Executor,必须将任务表述为一个Runnable。在大多数服务器应用程序中都存在一个明显的任务边界:单个用户请求。但有时候任务边界并非显而易见。 我们要解决的就是这种情况下如何找出可发掘的并发性。例如即使在服务器应用程序中,在单个用户请求中还存在着可发掘的并发性,例如数据库服务器。下面我们将学习几个例子来了解:1.串行的页面渲染器实现页面渲染器的最简单的方法是对HTML文档进行串行处理:当遇到文本标签时,将其绘原创 2020-11-18 17:44:55 · 133 阅读 · 0 评论 -
Java并发学习之Executor框架
一.我们为什么需要Executor框架?在上一篇博客中我们可以了解到,任务是一组逻辑工作单元,而线程则是使任务异步执行的机制,而且我们学习了两种通过线程来执行任务的策略:1.把所有任务放在单个线程中串行执行 , 2.将每个任务放到各自的线程中执行但是上面的两种策略都存在严格的限制:串行执行的问题在于其糟糕的响应性和吞吐量。为每个任务创建线程的问题则在于资源管理的复杂性。那么我们有没有方法能较好的解决上面的问题呢?有,就是我们的Executor框架,它极大的简化了线程的管理工作,Java库中的ja原创 2020-11-17 13:18:06 · 202 阅读 · 0 评论 -
Java并发学习之执行任务
一.执行任务其实大多数的并发应用程序都是围绕着“ 执行任务“来构造的 。1.什么是任务?任务通常是一些抽象且离散的工作单元,我们通过把应用程序的工作分解到多个任务中简化程序的组织结构,提供一种自然的事务边界来优化错误恢复过程,以及提供一种自然的并行工作结构来提升并发性。2.在线程中执行任务当围绕执行任务来设计应用程序时:1)第一步就是要找出清晰的任务边界。在理想情况下,各个任务之间是相互独立的,一个任务不依赖于其他任务的状态,结果或者边界效应。 独立性有助于实现并发,因为如果存在足够多的处理原创 2020-11-16 15:59:36 · 222 阅读 · 0 评论 -
Java并发学习之构建高效且可伸缩的结果缓存
一.缓存缓存是一种非常好的机制,几乎所有服务器应用程序都会使用某种形式的缓存,缓存的目的是以牺牲一些内存的方式重用之前计算结果的方式达到降低延迟,提高吞吐量的效果。二.开发高效且可伸缩的缓存1.第一次尝试1).在下面代码中的Computable<A,V>接口中声明了一个方法Computable,其输入类型为A,输出类型为V。2).在ExpensiveFunction中实现了Computable,并且其中的compute方法需要很长时间的计算,如果每次都调用这个方法,性能将会很低,所以我原创 2020-11-15 10:53:19 · 319 阅读 · 0 评论 -
Java并发学习之同步工具类
一.同步工具类概述1.什么是同步工具类?同步工具类可以是任何一个对象,只要他可以根据其自身的状态来协调线程的控制流。例如:阻塞队列可以作为同步工具类,还有其它的同步工具类:信号量(Semaphore),栅栏(Barrier),闭锁(Latch)。在java类库中还包括一些其他的同步工具类,如果这些类无法满足我们的需求,我们可以通过某种机制创建自己的同步工具类。2.同步工具类的结构化属性:1)它们封装了一些状态,这些状态将决定执行同步工具类的线程是继续执行还是等待。2)它们还提供了一些方法可以原创 2020-11-14 14:07:42 · 211 阅读 · 2 评论 -
java并发学习之阻塞方法与中断方法
一.阻塞方法1.线程会阻塞或暂停执行的原因有很多种,比如:等待I/O操作结束,等待获得一个锁,等待从Thread.sleep中醒来,或者等待另一的线程的计算结果。2.当线程阻塞时,它通常只是被挂起而不是结束,此时的线程会处于阻塞的一种状态,这要视情况而定。3.阻塞操作与普通操作的差别在于,被阻塞的线程必须等待某个不受它控制的事件发生后才能继续执行,比如,等待I/O操作的完成,而在I/O操作期间其时间是不确定的。当这个事件发生时,线程会被置回可运行状态,并可以再次被调度执行。4.BlockingQue原创 2020-11-13 20:48:50 · 314 阅读 · 0 评论 -
Java并发学习之并发容器
上一篇博客主要学习了java中的同步容器,但在一些情况下,同步容器也会出现线程安全性的问题,如需要进行一些复合外部操作时,进行迭代时容易发生ConcurrentModificationException错误。本篇博客主要学习一个相对于同步容器更好的容器集合:并发容器一.并发容器在Java 5.0后提供了多种并发容器类来改进同步容器的性能,它们所在的位置为:java.util.concurrent包中。1.为何要引入并发容器?我们知道,同步容器将所有对容器状态的访问都串行化来实现线程安全性,但这种方原创 2020-11-02 18:56:32 · 168 阅读 · 0 评论 -
Java并发学习之同步容器类
很多神秘的东西其实早已存在,只要我们善于寻找。-----Hacker DoreJava平台类库包含了丰富的并发基础构建模块,例如线程安全的容器类以及用于各种协调多个相互协作的线程控制流的同步工具类。一.同步容器类Java中的普通容器包uitl中的同步容器类有:Vector,Hashtable,Stack。我们还可以通过Collections类来获得相应的安全的容器类:这些类实现线程安全的方式是将它们的状态封装起来,并对每个公有方法都进行同步,使得每一次只有一个线程能访问容器的状态。1.同步容器类的原创 2020-10-29 16:29:56 · 200 阅读 · 0 评论 -
Java并发学习之对象的组合(设计线程安全的类)
一.本章概述本章将介绍一些组合模式,这些模式能够使一个类更容易成为线程安全的类,并且在维护这些类时不会无意的破坏类的安全性保证。学习目标:1.设计线程安全的类2.实例封闭3.线程安全性的委托4.在现有的线程安全的类中添加功能二.具体学习1.设计线程安全的类在设计线程安全的类的过程中,需要包含下面三个要素:1)找出构成对象状态的所有变量要分析对象的状态,首先从对象的域开始:a.如果对象中所有的域都是基本类型的变量,那么这些域将构成对象的全部状态b.如果在对象的域中引用了其他的对象,那原创 2020-10-26 20:39:45 · 177 阅读 · 0 评论 -
Java并发学习:线程不安全类和安全类基础
一.何为线程不安全类?一般认为,当多个线程并发的对一个类对象进行操作后发生了线程安全问题,那么这个类就是线程不安全的类。那么就有人认为:那为什么要编写线程不安全的类呢?把所有类都编写成线程安全的类不就行了,这是不现实的,我们知道,实现线程安全就要付出一定的性能开销,在有些情况下使用线程不安全的类性能要比使用线程安全的类的性能要好很多。总结:线程不安全的类的性能一般要比线程安全的类高。二.Java中线程不安全的类与其对应的安全类我们在进行java编程时,有必要区分java库中一些线程安全和不安全的类原创 2020-10-19 10:46:51 · 422 阅读 · 1 评论 -
java并发学习:线程封闭
线程封闭一.什么是线程封闭?简单来说,使线程间数据不共享的技术称为线程封闭二.这样的技术有哪些?1.栈封闭:局部变量局部变量的固有属性之一就是封闭在执行的线程中,它们位于执行线程的栈中,其他线程无法访问。why?下面来详细了解什么是局部变量:首先,我们知道局部变量定义在方法中,在执行方法时产生,方法执行完毕后销毁,由于这个特性使多个线程访问方法时,方法中的局部变量会被产生拷贝到一份到线程栈单独存在中,而导致局部变量线程间隔离。下面我们看个例子:package Concurrency;原创 2020-10-15 19:39:35 · 213 阅读 · 0 评论 -
Java并发:安全发布对象
一.概念1.什么是 发布对象?使一个对象能够被当前范围之外的代码所访问,我们就称发布了这个对象。下面例子解释何为对象发布:public class Test{ private String[] states={"c","a","r"}; //这个方法对外发布了此类的states对象 public String[] getStates(){ return states; } public static void main(String[] args){原创 2020-10-12 09:51:43 · 151 阅读 · 0 评论 -
Java中的并发:线程安全性
一.什么是线程安全性?当多个线程访问某个类时,不管运行时环境采用何种调度方式,或者这些进程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,则这个类是线程安全的。二.线程安全性具体体现在哪儿?1.原子性:提供互斥访问,同一时刻只能有一个线程对它进行操作。java中如何体现原子性的:Atomic包中的类主要通过CAS实现原子性CAS的含义是:CompareAndSwap 原理是:public final int getAndAddInt(Object va原创 2020-10-11 10:45:47 · 306 阅读 · 0 评论 -
并发基础:Java内存模型
一.现代计算机的并发问题1.现代的多CPU计算机已经普及,也就意味着有多Cache,并发时也就意味着存在着一定的风险:现在我们要让计算机计算1+1-1的操作,计算机进行多核并发运算:假如两个CPU同时从主存中读到同一个数据1存到各自的缓存中,CPU1将其加1结果2存到主存中,另一个CPU2将其减一结果0存到主存中,如果是CPU1的存入执行先于2,那么最后结果为0,反之结果为2,它们都不是正确的结果,我们要的正确结果为12.对于CPU多缓存的并发数据安全问题,诞生了MESI协议,该协议用于保证多个C原创 2020-10-11 09:30:29 · 105 阅读 · 0 评论