多线程
大力海棠
蓝桥杯Java组个人赛省二,麻瓜ACMer的北京尚学堂·百战程序员( ̄y▽ ̄)~*
展开
-
高并发笔记:StampedLock
回顾读写分离锁假如使用synchronized关键字或者重入锁ReentrantLock来对读写操作进行加锁,在多个读写线程情景下效率是非常低的,因为独占锁的方式,使得读线程与读线程,读线程与写线程之间都必须等待。对于读-写操作之间的等待,倒是合理的,防止脏读,假如写操作对数据做完修改后,还没有提交,读操作就进行了读取数据,写操作提交数据后,读操作即读到了脏数据,假如读操作之后利用读到的数据进...原创 2019-11-18 18:15:15 · 246 阅读 · 0 评论 -
ThreadLocal:不同于“锁”的优化
现在都是多核CPU了,多线程方式可以提高系统的性能,充分利用各个CPU,但是,多线程也增加了很多额外的开销,例如线程之间的切换,线程调度,还有最重要的多线程同步的问题,通常我们都会使用锁来控制线程同步,临界资源的访问通常我们都只加上一把锁,这样做的问题是,一个线程占用了这把锁,其他想要访问临界资源的线程就只能停下来等待,等待锁的释放,如果一个线程拿住了锁后,久久不放,那么越来越多的其他线程被阻塞,...原创 2019-04-29 17:49:59 · 766 阅读 · 0 评论 -
生产者-消费者中的缓冲区:BlockingQueue接口
BlockingQueue接口使用场景相信大家对生产者-消费者模式不陌生,这个经典的多线程协作模式,最简单的描述就是生产者线程往内存缓冲区中提交任务,消费者线程从内存缓冲区里获取任务执行。在生产者-消费者模式中最重要的就是这个内存缓冲区,可能你会疑问,为什么不让生产者直接把任务提交给消费者来执行,而是要通过一个中间媒介,也就是一个缓冲区来交换任务?通过缓冲区,可以缓解生产者和消费者之间的速...原创 2019-05-20 17:04:46 · 2470 阅读 · 0 评论 -
特定的无锁场景问题(如无锁栈)解决:AtomicStampedReference
虽然无锁比较交换让代码看起来比直接加锁复杂一点点,但是无锁比较交换能提供更高的效率,没错,且不存在死锁问题,但是无锁操作不是所有场景下都是安全的。先用最简单直白的概括回顾下CAS,有三个参数V,E,N,只有当“预期值”E和对象V的值相等时,才把V的值更新为“更新值”V。可以看到,是否修改V的值,取决于V的值和E是否相等,如果不相等,那么程序就会重新读取V的值,直到V的值与E相等后,才做修改操作(当...原创 2019-05-13 17:08:21 · 497 阅读 · 0 评论 -
无锁缓存框架Disruptor如何解决伪共享问题?
无锁的生产者–消费者在上一篇使用BlockingQueue队列实现的生产者–消费者模式中,从BlockingQueue队列的源码可以看到两点值得注意,第一是为了保证线程安全,BlockingQueue使用了重入锁。第二,为了实现缓冲区满时,生产者等待,缓冲区空时,消费者等待,以及何时唤醒生产者/消费者的问题,使用了Condition来完成线程阻塞与唤醒。既然选择了使用锁来完成线程同步,那么在多...原创 2019-05-27 17:02:29 · 831 阅读 · 1 评论 -
并行设计模式:并行流水线与并行查找
流水线与指令重排我们知道进程切换开销是很大的,CPU首先保存当前被中断进程现场,然后把系统堆栈指针保存到PCB中,接着去处理中断,选择下一个占用CPU的进程。引入线程的目的就是减少了系统的时空开销,因为现在多核处理器已经十分普遍,设想如果一个程序它只有一个线程,那么在一个双核处理器上运行该程序,那么同一时刻只有一个核在运行,另一个核就处于空闲状态,导致系统资源浪费。程序使用多线程,可以充分利用...原创 2019-06-03 17:01:52 · 2984 阅读 · 0 评论 -
先提交后获取:Future和FutureTesk的异步执行
在上一篇日志中,并行执行下的多线程协作完成查找操作里,我让每一个查找线程实现了Callable接口,从主线程中也看到,使用了Future<Integer>泛型接口来接收线程的返回结果。想了一下,觉得有必要补上一篇日志,总结下自己对Future模式的学习。使用Runnable还是Callable?通常我们创建线程都是继承或实现Runnable接口,使用Callable接口和Run...原创 2019-06-10 17:04:33 · 711 阅读 · 0 评论 -
使用NIO构建服务器端和客户端(上)
构建一个最基本的服务器端和客户端连接,因为网络的读写操作都是使用标准IO,所以通常使用的是Socket处理机制来实现。假如要实现一个可以为多个客户端响应的服务器,服务器端为每一个建立了连接的客户端分配一个线程,每一个线程只为一个客户端连接服务,这种多线程的服务器开发是十分常见的,它的简单实现如下。多线程服务器简单实现要建立能处理多客户端连接处理的服务器,需要一个线程池,为每一个提交建立连接...原创 2019-06-17 16:53:11 · 1569 阅读 · 2 评论 -
线程组 - 关联线程与管理
线程组与线程池以前接触学习线程组时,并没有太深入去了解其中的东西,原因是当初和同学讨论赛车游戏中,倒计时出发场景,是怎么实现多个线程同时启动的?所以就转去学习线程池了。不过后来发现其实是可以用CountDownLatch或者CyclicBarrier - -、。现在重新拾起了线程组,决定写篇日志,总结一些线程组相关。创建线程池的目的,相信大家都很熟悉,就是为了解决许多的线程频繁创建和销毁,...原创 2019-08-19 16:21:20 · 777 阅读 · 0 评论 -
CAS实例:线程安全的读写队列
在并发环境下ArrayList和HashMap都是不安全的,对于ArrayList,假设多线程对同一个ArrayList一起做写入操作,有可能多个线程同时对ArrayList中同一个位置做赋值,导致最后期望数据和实际数据不一致。HashMap一样有可能出现数据不一致这个问题,且使用HashMap有可能出现更大的灾难,那就是多线程对同一个HashMap做遍历过程中可能会破坏链表的结构,出现如两个结点...原创 2019-04-08 17:02:43 · 665 阅读 · 0 评论 -
ForkJoin框架的分而治之
分而治之的思想不陌生了,归并排序用到,即把待排序列递归地等分成两个子序列,并排序,这样在不停递归等分,排序归并过程中,会得到若干个有序序列,因为递归过程是等分成左右序列嘛,所以最后会得到两个有序的序列,再做一次归并操作即可。外部排序中也用到,现在在多线程中也有,在多线程中分而治之思想有基于数据的分割和基于任务的分割。拿基于数据的分割来说,例如对于一个大文件的下载,使用多个线程分别下载一个大文件的不...原创 2019-04-01 19:57:15 · 318 阅读 · 0 评论 -
自定义:线程池和它里面的线程
顾名思义,线程池,里面就是放线程的,使用线程池的目的是为了线程的复用,前面说过,(如果)大量线程的不停创建和销毁是很浪费时间的,而且线程被创建后,本身也会占用内存,所以,如果大量地使用线程,会降低系统的性能。线程池中的线程没什么不同,都是通过ThreadFactory接口创建出来。来看看这个“线程工厂”ThreadFactory的源码:public interface ThreadFact...原创 2019-03-25 20:24:05 · 1196 阅读 · 0 评论 -
重入锁和公平锁
同步控制的方法除了synchronized外,还可以用重入锁来实现,重入锁的类是java.util.concurrent.locks.ReentrantLock类。调用重入锁的两个方法lock()和unlock()来包裹保护临界区操作,也就是加锁和释放锁的过程是显式的。直接来看一段重入锁的使用代码:第11行到15行对临界资源value(也就是我们希望得到同步控制的资源)的++操作进行上锁保...原创 2019-01-21 18:57:17 · 690 阅读 · 0 评论 -
避免死锁:中断响应与等待限时
调用重入锁的lock()方法去申请锁,如果锁被占用了,那么线程就会一直等待锁,有时候这样的情况并不好,如果等待锁的时间太长了,应该去干点别的事情,回来再申请锁。也就是说,一个线程等待锁时,可以中断等待,继续干线程自己的事情。那么如果让一个线程不会一直等待锁的申请,转而去响应中断呢?就要用到lockInterruptibly()方法,是一个可以对中断进行响应的锁申请动作。具体来看一段代码:...原创 2019-01-28 19:42:48 · 1285 阅读 · 0 评论 -
那么要怎么终止一个线程呢?
虽然Thread.stop( )方法可以结束一个线程,但是eclipse已经将这个方法标注成一个“废弃”的方法,也就是不推荐使用,原因大家都知道,就是stop( )方法直接终止线程并释放掉锁,容易造成一些对数据进行修改的线程出问题,例如导致多个线程读到不一致的数据的情况。看看下面这个例子:代码要做的事情就是新建一个写线程和一个读线程,写线程修改变量的值,读线程把值显示出来。写线程在31...原创 2019-02-04 17:41:03 · 886 阅读 · 0 评论 -
重入锁:Condition方法线程等待
前面的学习学过,为了多线程之间的同步,有wait( )和notify( )两个方法使用,不过这两个方法是在Object类上的,也就是所有的对象实体都有这两个方法。回顾一下,调用wait( )方法后,线程会在这个对象的等待队列上等待,直到其他线程调用notify( )方法,notify( )方法会在等待队列上随机唤醒一个等待线程,注意它是随机的!!随机唤醒!!对象的wait( )和notify(...原创 2019-02-11 18:26:40 · 537 阅读 · 0 评论 -
两种线程“等待”,“门闩”和“栅栏”
CountDownLatch(门闩)和CyclicBarrier(栅栏)都是java.concurrent里的多线程控制工具类,我这里说他们两个都是控制线程等待,它们都像是一个计数器,让某一个线程等待计数完成后再执行,但是又有些不同,CountDownLatch是通过计数完成后才执行线程来控制线程等待,而CyclicBarrier可以是线程执行到某一处后等待计数,计数完成后再继续执行。简单来说...原创 2019-03-04 20:24:03 · 868 阅读 · 0 评论 -
LockSupport:不用担心线程被永久阻塞
让线程“等待”的方法有很多,例如wait()和notify(),不过这两个方法是对对象做操作,它们不在Thread类中。如果一个对象object o调用wait()方法,那么它就会进入object的等待队列中,直到notify()方法被调用后,从这个等待队列中随机选择唤醒一个线程,这种选择是随机的,是不公平的。还有suspend()和resume()方法,不过既然是被标注为废弃方法,就很少用了...原创 2019-03-11 20:23:35 · 740 阅读 · 0 评论 -
三种线程池的内部实现&有界/无界队列
以前学.NET时,为了不用每次连接数据库都去新建一个连接字符串,老师让我们把数据库连接字符串保存到webconfig文件里。现在看多线程,Java虽然有自动回收,线程在run()方法执行完后就会自动回收,但是线程的创建和销毁都是需要时间,如果大量地创建线程,不光需要系统花费大量的内存,线程的创建与销毁也要浪费很多的时间,最后可能让程序运行的很慢。既然频繁的创建和销毁线程会降低系统性能,那么有没...原创 2019-03-18 20:22:59 · 7096 阅读 · 0 评论 -
volatile与synchronized谁更安全?
学习JMM时发现,并发程序下的数据一致性很重要,一个线程对某个数据做了修改,怎么保证另一个线程看到的这个数据是修改后的或者说是正确的?JMM的建立就是围绕三点:原子性、有序性和可见性。 原子性指的是一个操作是不可被打断的,即多个线程共同执行时,某个线程的操作不会被其他线程干扰。有序性问题比较难理解,在程序执行时有可能会出现指令重排,重排后的指令与原指令顺序就不一定相同了。你肯定想问为...原创 2019-01-14 20:30:36 · 636 阅读 · 0 评论