Code Monkey home page Code Monkey logo

multithreadlearning's Introduction

线程的风险 1.安全危险 线程并发执行时,由于内存的可见性已经顺序执行被破坏可能会导致执行结果与预想期望不同的风险 2.活跃度风险 即使保证了内存可见性以及顺序的有效执行,也会因为在多线程环境下发生线程竞争资源导致的线程的活跃度危险。 eg:死锁,饥饿 ,活锁 比如多个线程竞争A,B两个线程,A占有了B期望的资源,B锁了A的资源,如果咩有外力的作用,可能这两个资源会无休止的相互等待下去。 Q:死锁发生的条件?

3.性能风险 多线程的目的其中之一就是提高程序的系能,例如QPS,TPS,以及RT,如果线程不能处理好性能问题,那么多线程开发到不如单线程。 并且计算机底层的线程切换会有一系列开销,所以我们可以在编译器层面(JVM)上多线程锁进行优化。例如:偏向锁锁会偏向当前持有锁的线程,参数-XX:+UsebaisedLocking默认启动的,在没有竞争的情况下,后的偏向锁的线程,在将来进入同步块石,不需要做同步,但是当其他线程请求相同的锁时,偏向模式结束,在竞争激烈的场合,偏向锁会增加系统的负担 自旋锁:当竞争存在时,如果线程可以很快获得锁,那么可以不再OS层挂起线程,让线程做几个空操作,JDK1.6中-XX:+Usespinning开启,在1.7中,去掉了此参数,改为内置实现。 若同步块很长,自旋失败,会降低系统的性能。若同步块很撑,自旋成功,节省线程挂起的切换时间,提高系统系能。

可重入锁: Reentrancy Lock,将锁的级别有每调用,改为每线程,通过没每个所关联一个请求技术和一个占有它的线程。举个例子,子类继承父类的synchronized方法,并在改方法中调用父类的改方法,若没有重入锁,那个该方法就会进入死锁的状态

volatile 变量也有限制,他可以保障内存可见性,但是并不能很好的支持自增操作的原子性。但枷锁可以保证原子性和内存可见性。
发布和溢出

concurrentHashMap 使用的是分离锁来提高并发的效率。(读写锁?) 在并发变成下,size和isEmpty这样的方法几乎没用处,因为目标是变化的,所以对这些操作的需求被弱化了

Blocking queue 提供了可阻塞的put和take方法,若queue满了,put方法会被阻塞直到用空间可用,如果queue是空的,那么take方法将被阻塞,直到有元素可用。 阻塞队列支持生产者消费者设计模式,用它可以解除生产者和消费者代码之间的依赖关系,降低了耦合度,推荐使用阻塞队列解决上述问题。 LinkedBlockingQueue和ArrayBlockingQueue是FIFO队列, PriorityBlockingQueue是一个按优先级书序排序的队列可以用Comparatoy进行排序。 SynchronousQueue,这不是一个真正的队列,他不会为队列元素提供存储空间,适合消费者充足的场合。???

双端队列???

latch闭锁,等待未完成的事件完成,再开始后续的作业。
CountDownLatch包含一个计数器,初始化为一个整数,用来表现需要等待的事件数,countDown方法对计数器做减操作,表示一个时间已经发生。若计数器的值非零,则await会阻塞到计或者等待线程中断或超时。

FutureTask 同样可以作为闭锁。接受callableTask,可以有返回值。

信号量 semaphore,通过设定许可数permit,如果还有许可,则acquire会被阻塞,直到有可用的许可,release方法想信号量返回一个许可。
它可以来实现资源池,比如数据库连接池。当它为空时,向他请求资源会失败。构建这种池比较简单,当池为空时,你需要阻塞它,当它不为空时,接触阻塞。,如果你以池的大小初始化一个semaphore,从池中获取资源之前,应该调用acquire方法获得一个许可,调用release方法将许可返回资源池。若资源池为空,这acquire方法会阻塞,直到池不再为空。

关卡,barrier 类似于闭锁,它们都能够阻塞一组线程,直到某些事件发生。 它与闭锁不同的是,关卡中所有线程必须同时到达关卡点,才能继续处理。而闭锁等待的是时间,关卡等待的是其他线程。
cyclicbarrier 允许一个给定数量的成员多次集中在一个关卡点,这在并行迭代计算中非常有用,这个算法会将一个问题拆分成一系列互相独立的子问题。当线程到达关卡点时,调用await,await会被阻塞,直到所有线程都到达关卡点。如果所有的方法都被成功突破,这样所有线程都被释放,关卡会重置已被下次使用。如果await方法调用超市,或者线程都被释放,那么则认为关卡是失败的,所有对await方法未完成的调用都通过BrokenbarrierExcwption 终止。 若成功的通过关卡,await方法为每一个线程返回一个唯一的到达索引号,可以用来选举产生一个领导。在不涉及IO或者访问共享数据是,Ncpu活Ncpu+1个线程产生最有吞吐量???(page101)
Wxchanger是关卡的另一种形式。

为计算结果简历高效,可伸缩的高速缓存。
几乎每一个服务器应用程序都使用某种形式的高速缓存,服用已有的计算结果可以多段等待时间,提高吞吐量,代价是占用更多的内存。

Page110中有一些有用的tips,以下是摘要:
所有的并发问题都归结为如何访问并发状态,可变状态越少,保证线程安全越容易。
尽量将域声明为final,除非他们是需要可变的。
不可变对象是线程安全的,可以信赖。 封装使管理复杂度变得可行。
用锁来守护每一个变量
对同一不变约束中的所有变量都使用相同的锁
在运行复合操作期间持有锁
在飞同步的多线程情况下麻烦问变量的程序是存在隐患的
不要依赖于可以需要同步的小聪明
在设计过程中就要考虑线程安全,或者在文档中明确说明它不是线程安全的。
文档化同步策略

但并不是创建的线程越多,你的程序越好,线程过多会消耗大量的系统资源,占用更多的内存。应该限制线程的数目,这受到JVM的启动参数,Thread的构造函数中请求栈大小的影响,以及底层操作系统的限制。
它可能在开发测试阶段能够运行良好,但在应用程序部署到线上之后暴露出问题。

任务是逻辑上的工作单元,线程则是是任务异步执行的工具。

page117.

线程池。
newFixedThreadPool创建定长的线程池,每当提交一个任务就创建一个线程,知道达到池的最大长度,这是线程池会保持长度不再变化,会阻塞,知道有空闲的线程(若一个线程由于非预期的exception而技术,线程池会补充一个新的线程),

newCachedThreadPool传建一个课缓存的线程池,如果当前线程池的长度超过了处理需要时,他可以灵活的回收空闲的线程,当需求增加时,他可以灵活地添加新的线程,而并不会对吃得长度做任何的限制。

newSingleThreadPool穿件一个单线程化的executor,它只创建唯一的工作线程来执行任务,吐过这个线程异常结束,会有另一个取代他,executor会保证任务yizhao任务队列所规定的顺序(FIFO,LIFO,优先级)执行。

newScheduleThreadPool穿件一个定长的线程池,并且支持定时的以及周期性的任务执行,类似于Timer.

ExecutorService能够管理executor的生命周期(3种状态:运行,关闭,终止),它最初创建后的初始状态是运行状态。shutdown方法会启动一个平缓的关闭过程:停止接收新的任务,同事等待已经提交的任务完成--包括尚未开始的威武。shutdownNos方法会启动一个强制关闭过程:阐释取消所有运行中的任务和拍照队列中尚未开始的任务。 在关闭后提交给executorService中的任务,会被拒绝执行处理器(rejected executor hander)处理(是由ExecutorService的一种实现,ThreadPoolExecutor提供的)。
可以用newScheduledThreadPool来取代Timer,后者只会启动一个线程,若执行的任务较为耗时,会导致其他Timertask 的实效性出现问题;若抛出了UnexpectedException,则Timer的行为将会无法预料:会终止timer线程。这种情况下Timer也不会再重新恢复线程的执行了。新的任务将不会调用。这个问题叫做线程泄漏。 另外我们可以用DelayQueue来构建自己的调度服务。他是BlockingQueue的实现。

Page127

应用线程池

1。线程饥饿死锁。 实质若在一个单线程化的executor中,一个任务将另外一个任务提交到相同的executor中,并等待新提交任务的结果,则很容易发生死锁(第二个任务会因为等待第一个任务而滞留在工作队列中)。在一个大的线程池中,如果所有线程真行的任务都阻塞在线程池中,等待着处于同一工作队列的其他任务。那么会发生同一的问题,这被称作线程饥饿死锁 耗时操作 2.耗时操作 如果提交的任务时间周期过长,及时不会出现死锁,线程池的响应也会变得很差

制定线程池的大小 它的长度不是一门精确的学科,只要避免过大会过小两种极端,例如使用Runtime.availableProcessors的结果,进行动态的计算。 要区分任务的类型,例如cpu密集还是I/O密集。如果任务类型比较复杂,建议将任务进行划分,使用不同的线程池。 若是计算密集型的任务,假设有N个处理器,则可以设置N+1个线程的线程池。

ThreadPoolExecutor,为Executors中的工厂newCachdThreadPool,newFixedThreadPool以及newScheduledThreadExecutor返回的。我们可以利用它来定制我们的线程池。

Page173

管理线程队列。(线程池优点) 原本如果线程过多,未处理的线程会竞争已经空闲的线程,消耗了资源。如果使用线程池的话,还未处理的线程会被放在线程池所包含的BlockingQueue中。任务排队有3中基本方法:无限队列,有限队列和同步提交(synchronous ahndoff) newFixedBlockingQueue和isingled使用的是无限队列LInkedBlockingQueue。如果所有的工作线程都处于忙碌状态,任务将会在队列中等候。如果任务持续的快速到达,超过了他们被执行的速度,队列也会无限制的增加。

一个较为稳妥的策略就是使用优先队列,比如ArrayBlockingQueue或者有限的LinkedBlockingQueue以及PriorityBlockingQueue。有助于避免资源耗尽。但队伍满之后,新的任务怎么办?饱和策略可以出来这个问题。技巧:一个大队列和一个小池,可以控制对内存和CPU的使用,减少上下文的切换,但可能要接受潜在吞吐量约束的开销。 对于庞大活无限的池,可以使用SynchronousQueue,绕开队列,将任务直接交给工作线程。只有当池是无限的时候或者可以接受任务呗拒绝,它才有价值。newCachedThreadPool就使用了这种方式。 当任务彼此独立时,有限的工作队列是合理的,当任务仙湖依赖时,可以选择用无线的线程池来处理任务。

饱和策略 当有限队列充满后,饱和策略开始工作。ThreadPoolExecutor的饱和策略可以通过setRejectedExecutionHandler来修修改。终止(默认的策略,会跑出RejectedExecutorException),遗弃(放弃这个任务),调用者运行(不会丢弃和跑出异常,会把任务退回到调用者哪里)

multithreadlearning's People

Contributors

happyxiaodan avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.