线程

线程运行时 为每个线程开辟独立的内存空间 线程之间不可见
内存可见性(Memory Visibility)是指当某个线程正在使用对象状态而另一个线程在同时修改该状态,需要确保当一个线程修改了对象状态后,其他线程能够看到发生的状态变化。


线程_第1张图片
微信图片_20180809094255.png

可见性错误 对共享数据进行操作时 线程a完成了写的方法 但是线程b不能及时获取线程a写之后的值

Volatile关键字
在有更新的操作完成后 通知其他线程 (也可以说是所有的操作都在主线程中操作)
当多线程操作共享数据时,可以保存内存可见性 相对于sync 是较轻量级的同步策略
不能保证变量的原子性

原子变量CAS算法(compared and swap) 比较并替换
内存地址 V
旧的预期值 A
新的目标值 B
当 V == A 时,V=B;否则不做任何操作
缺点:
1.当cas失败后 会一直进行尝试 如果cas长时间不成功 会带来大量开销
2.只能保证一个共享变量的院子操作
3.ABA问题
当线程A对V 赋值多次后 还是原来的值 那么就出现了ABA问题
Java 提供了 AtomicStampedReference 版本戳 解决
使用Java Atomic~ 解决Volatile关键字的不能保证内存原子性问题

锁分段机制ConcurrentHashMap
所有访问HashTable的线程都必须竞争一把锁,效率低
ConcurrentHashMap中使用了一个包含16个锁的数组,每个锁保护所有散列桶的1/16,其中第N个散列桶由第(N mod 16)个锁来保护


线程_第2张图片
分段锁.png

CountDownLatch闭锁
在完成一组正在其他线程中执行的操作之前 它允许一个或多个线程一直等待

Callable接口
类似于Runnable接口 有返回值 可抛出异常
依赖FutureTask 使用FutrueTask 包装Callable

Lock 同步锁 ReentrantLock
Condition 控制线程通信

    Lock lock = new ReentranLock();
    Condition condition = lock.newCondition();
    condition.await();//线程等待
    condition.signal();//线程唤醒

CopyOnWriteArrayList/CopyOnWriteArraySet 写入并复制
添加操作多时 效率低 因为每次添加的时候都会进行复制 开销非常大 并发迭代操作多时 可以选择
ReadWriteLock 读写锁
写写/读写 操作 需要互斥
读读 操作 不需要互斥

ForkJoinPool 分支/合并框架(运行时间>合并时间)
将一个大任务 拆分fork成若干个小任务 拆到不可再拆时
将所有的小任务进行join
工作窃取模式(work-stealing)
当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。
相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式上.在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态。而在fork/join框架实现中,如果某个子问题由于等待另外一个子问题的完成而无法继续运行。那么处理该子问题的线程会主动寻找其他尚未运行的子问题来执行.这种方式减少了线程的等待时间,提高了性能。

你可能感兴趣的:(线程)