南阳市宛城区建设局网站,合肥网站建设外包,网站搜索引擎优化报告,为女足世界杯创建一个网站多线程进阶相关知识点 一.CAS1.1 CAS的原子类1.2 实现自旋锁1.3CAS中的ABA问题1.4 ABA问题的解决 二. callable接口三.reentrantLock3.1 reentrantLock与synchronized区别 四.信息量 semaphore五. CountDownLatch六. concurrentHashMap6.1 concurrentHashMap的优点 一.CAS CAS … 多线程进阶相关知识点 一.CAS1.1 CAS的原子类1.2 实现自旋锁1.3CAS中的ABA问题1.4 ABA问题的解决 二. callable接口三.reentrantLock3.1 reentrantLock与synchronized区别 四.信息量 semaphore五. CountDownLatch六. concurrentHashMap6.1 concurrentHashMap的优点 一.CAS CAS compare and swap 比较并交换 比较交换的是内存和寄存器中的值 就能原子的完成一些复杂操作,达成无锁化编程. 1.1 CAS的原子类 1.比较相等 2.如果相等 就将新值赋值给address中 3.返回操作 但上述伪代码并不是原子的 这些代码是在java.util.concurrent.atomic包中的原子类,是基于CAS实现的. 1.2 实现自旋锁 实现自旋锁,如果this.owner不为空 就一直进行忙等 循环会一直执行下去 此处自旋的等 虽然没有放弃cpu 但是不会参与调度, 缺点会消耗很多CPU资源 1.3CAS中的ABA问题 CAS的判定本质上是判断是否有其他的线程从中间穿插进来. 我们先看一个例子 极端情况: 在t1执行之前 t3线程又给我账户充值了500块钱,我们就分不清楚到底是取了500块钱,还是取了又充值回去的,就会引起一个BUG. 1.4 ABA问题的解决 1.约定数据变化只能是单向的(要增就只能都增) 2.如果必须是双向变化的数据,我们可以引入版本号.版本号的数字就只能是增加或者减少的. 二. callable接口 我们前面学过实现runnable接口来完成线程问题,这里的callable接口有什么不同呢? runnable接口关注的是过程,而不是结果,所以提供的run方法,返回值为voidcallable接口关注的是结果,提供的call方法的返回值就是callable接口的泛型类 除此之外,在callable接口中,我们为什么不能直接将callable放到Thread的参数里面呢?因为Thread没有提供相应的构造方法,我们需要借助FutureTask来辅助实现 三.reentrantLock 它是一个可重入锁, 与synchronized类似. reentrantLock提供了两个方法, lock方法和unlock方法,但是如果unlock有时会无法解锁,这是因为碰到return或者异常之后就会执行不到unlock,所以必须将unlock方法与try-finally方法连用. 3.1 reentrantLock与synchronized区别 区别1 : reentrantLock方法提供了tryLock方法 普通的lock方法进行加锁,如果无法加锁,就会阻塞 tryLock方法加锁不成,不会阻塞,会直接返回false 区别2 : reentrantLock提供了公平锁的实现 所谓公平锁就是要遵循先来后到的原则,通过队列记录加锁线程的先后顺序. 区别3: 搭配的等待通知不一样 synchronized搭配的是 wait-notify方法 reentrantLock搭配的是Condition方法 四.信息量 semaphore 信息量表示 可用资源的个数 申请一个资源,可用资源的个数就会减1 称为P操作 释放一个资源,可用资源的个数就会加1 称为V操作 acquire表示申请一个资源 release表示释放一个资源 五. CountDownLatch 它的目的就是 多线程执行一个任务, 把大的任务拆分成几个部分 ,分给每个线程执行. 六. concurrentHashMap 我们知道哈希表中有 HashMap , Hashtable 在多线程中,我们知道.HashMap是线程不安全的所以不予考虑. Hashtable在关键方法上都有synchronized加锁,但是我们也不常用, 这就引入了concurrentHashMap 6.1 concurrentHashMap的优点 缩小了锁的粒度 在Hashtable中 如果修改两个不同链表中的元素时,不会有线程安全问题.如果是修改同一个链表上的元素时,就会发生锁冲突,有线程安全问题. 在concurrentHashMap中,给每一个链表都发了一把锁,因此就不会发生锁冲突.线程会更加的安全. 优点2 :充分的使用了CAS的原子操作,减少了加锁. 优点3 : 针对扩容问题,增加了优化 我们知道,在哈希表中有负载因子:描述了桶上平均有多少元素. 哈希表的查找效率是O(1) 但是你超过了原有元素的个数之后,我们要进行扩容,把旧的元素全部添加到新的元素上,如果本身有很多元素的话,会非常消耗时间. HashMap的做法是一次性的全部扩容,就会非常耗费时间 concurrentHashMap的做法是 一次扩容一部分 分多次来扩容 ,避免了一次性的耗费时间太多的问题.避免出现某一时间段卡的情况.