voliate courrenthashmap cas aqs montior syn lock threadlocal

AtomicInteger内部声明了一个volatile修饰的变量value用来保存实际值  cas
do {  getAndIncrement
    var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

hashmap 数组+链表 Node<k,v>[] table   Map m = Collections.synchronizeMap(hashMap);
Node<k,v> hash key value next
get->table[hash(key)] 遍历链表找key
put->判断位置,有值就比较或者添加  resize  扩容后,重新计算元素新的位置  扩容的时候可能导致重新分配链表指针变成1->2->1 变成死循环
而JDK8就不会出现这个问题,它在这里就有一个优化,它使用了两个指针来分别指向头节点和尾节点,而且还保证了元素原本的顺序。!!!

ConcurrentHashMap 数组+链表+红黑树 不允许key value为空
put  
/如果i位置没有数据,就CAS直接无锁插入 initTable
//如果在进行扩容,则先进行扩容操作
//如果以上条件都不满足,那就要进行加锁操作,也就是存在hash冲突,锁住链表或者红黑树的头结点  

synchronized 每个对象都有一个monitor对象,多线程操作 monitorenter monitorexit 

CAS compareAndSwapInt(this, valueOffset, expect, update);  内存值,期望值,更新值  失败就重新读取值在更新

AQS CountDownLatch ReentrantLock
volatile state变量 -> CAS -> 失败后进入队列等待 -> 释放锁后唤醒   ReentrantLock则提供了中断功能。
cas->tryAcquire-> addWaiter  
调用LockSupport的park方法阻塞住了当前的线程 unpark

CountDownLatch await(long timeout, TimeUnit unit);//在timeout的时间之内阻塞当前线程,时间一过则当前线程可以执行, countDown
初始化就state=n wait就加入队列挂起,down就state-1.  state=0的时候证明计数器已经递减完毕,此时会将AQS阻塞队列里的节点线程全部唤醒。!!!


线程池里的线程数量是否小于 corePoolSize,也就是 10,如果小于,直接创建一个线程出来执行你的任务  新来一个,也是直接创建,不是用空闲的
线上机器突然宕机,线程池的阻塞队列中的请求怎么办 麻烦先在数据库里插入这个任务的信息,更新它的状态:未提交、已提交、已完成。提交成功之后,更新状态为已提交状态

公平锁和非公平锁
公平锁:是指按照申请锁的顺序来获取锁 等待线程释放后,队列的第一个线程获取锁
非公平锁:线程获取锁的顺序不一定按照申请锁的顺序来的。  会自动加入队列,等待线程释放锁后所有等待的线程同时去竞争
ReentrantLock reentrantLock =  new ReetrantLock();//默认是不公平锁,传入true为公平锁,否则为非公平锁  程序员手动进行加锁和释放
synchronized 是非公平锁  编译器去保证锁的加锁和释放。
线程获取重量级锁在自旋阶段会造成无序的现象,一旦进入竞争队列就会是有序的!!!
可重入锁  同一个线程可以反复获取锁多次,然后需要释放多次  可以多次获取相同的锁 synchronized ReentrantLock一定要手动释放锁次数

每个对象都会有个隐形的监视器,用于线程的同步,和这个对象线程交互的方法一般有wait和notify及notifyall

共享锁和独享锁
ReadWriteLock 读锁是共享锁,写锁是独享锁

乐观锁和悲观锁
分段锁 1.7及之前的concurrenthashmap。并发操作就是分段锁,其思想就是让锁的粒度变小

三种针对Synchronized
偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁
轻量级锁 当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能
重量级锁 指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让其他申请的线程进入阻塞,性能降低

自旋锁指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU


线程安全:对共享变量操作,在多线程环境下很容易出现各种意想不到的的结果。
voliate  courrenthashmap cas aqs montior  syn lock threadlocal  

private static AtomicInteger atomicInteger = new AtomicInteger(0);
//去重sip dip type  目前只去重system,日志太多
atomicInteger.getAndIncrement();  getAndIncrement是先获取之前的值在增加  incrementAndGet增加返回后的值
int size = atomicInteger.get();
if(size >= 1000){
    atomicInteger.set(0);
    cacheMap.clear();  //1000key重复的数据去重丢掉
}

atomicInteger解决了原子性问题  ++操作  private volatile int value  通过无线循环自旋尝试更改值compareAndSwapInt
AtomicReference  atomicInteger但是没解决ABA问题  
AtomicStampedReference 不仅维护了对象值,还维护了一个时间戳  有两个预期!!! compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp)。

volitle能保证可见性,不能保持原子性!!也就是说只要一个线程对共享变量修改了,其他线程都能立即看到。  禁止进行指令的重排序 并不能保证原子性
如n=n+1、n++等,volatile关键字将失效,只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如n = m + 1,这个就是原级别的
如i = 1的赋值操作,但是像j = i或者i++这样的操作都不是原子操作,因为他们都进行了多次原子操作,比如先读取i的值,再将i的值赋值给j,两个原子操作加起来就不是原子操作了。
API来了解这些原子类 AtomicInteger、AtomicLong、AtomicReference等。   原子性成功或者不成功,解决不了aba
unsafe.compareAndSwapInt(this, valueOffset, expect, update); 内存值,期望值,更新值!!!   不一样就自选重新获取最新getIntVolatile
CAS  ABA问题的原因,就比较好给出解决方案了,加上时间戳(版本号)!!!!!  AtomicStampedReference   循环时间长开销大(考虑限制自旋的次数)
AtomicInteger能保证原子性,避免不了aba   线程安全的  如果在线程较多的情况下,效率会变的很低,因为没有加锁  会不断循环

https://www.jianshu.com/p/d10256f0ebea
hashmap可能会死循环 多个链表间a b c节点形成循环  当多线程并发扩容时就会出现环形引用的问题,从而导致死循环的出现,一直死循环就会导致 CPU 运行 100%!!!!
courrenthashmap 数组+链表+红黑树  hashmap也是  红黑树查询效率高  当链中键值对数量大于8才转换成红黑树,数量小于6才转换成链表
ConcurrentHashmap 和 Hashtable 都不支持 key 或者 value 为 null。  hashmap支持
抛弃了 JDK 1.7 中原有的 Segment 分段锁,put 而采用了 CAS + synchronized 来保证并发安全性。  CAS插入头结点 乐观锁
当添加定位到数组位置  for()没有节点Node,通过cas添加  如果该位置有链表,添加synchronized锁住头节点,做插入或者更新!!!!!!!!!!!!!!!!!  Node key value hash next
transient不虚拟化 sizeCtl<0表示其他线程已经在初始化了或者扩容了,挂起当前线程!!
size方面在put remove就会调用计算   AtomicInteger
哈希碰撞  解决哈希碰撞的常用方法是:开放定址法(线性探测再散列,二次探测再散列,伪随机探测再散列)和链表地址法,建立公共溢出区,再哈希法

cas就是乐观锁 提高性能 Compare And Swap  CPU开销较大

java对象都有一个Monitor与之对应,Monitor是实现Sychronized(内置锁)的基础  enter exit wait notify notifyAll
_owner:指向持有ObjectMonitor对象的线程_WaitSet:存放处于wait状态的线程队列_EntryList:存放处于等待锁block状态的线程队列_recursions:锁的重入次数_count:用来记录该线程获取锁的次数

synchronized 调用Monitor的方法enter exit指令以及对应的计数器  锁状态  CAS
修饰一个代码块 方法 这个对象  static这个类的所有对象  静态和非静态是两个锁,可同时获取
synchronized获取锁的线程由于要等待IO或者其他原因(比如调用sleep方法)被阻塞了,但是又没有释放锁,其他线程便只能干巴巴地等待,试想一下,这多么影响程序执行效率。一直无期限地等待下去
程执行发生异常,此时JVM会让线程自动释放锁。因此不会导致死锁现象发生
如果多个线程都只是进行读操作,所以当一个线程在进行读操作时,其他线程只能等待无法进行读操作,浪费效率。readLock可以

https://www.cnblogs.com/baizhanshi/p/6419268.html
Lock finally释放锁,不然死锁 !!!! tryLock避免死锁
tryLock 返回true false,不会一直等待  tryLock(long time, TimeUnit unit)会等待一段时间  通过time控制for
ReentrantLock  ReentrantReadWriteLock  WriteLock writeLock = new ReentrantReadWriteLock().writeLock();内部静态类  读锁共享  写锁线程独占 ReadWriteLock接口
newCondition:用于替代wait/notify。 await和signal,signalAll  unpark
lock声明为类的属性  方法局部变量每个线程都是不同的锁
如果有一个线程已经占用了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待释放读锁!!!
ReentrantLock lock = new ReentrantLock(true);公平锁 默认不公平  FairSync公平锁
ReenTrantLock的实现是一种自旋锁,通过循环调用CAS操作来实现加锁。它的性能比较好也是因为避免了使线程进入内核态的阻塞状态
ReentrantLock->NonfairSync->Sync->AbstractQueuedSynchronizer
https://blog.csdn.net/qq_29373285/article/details/85964460
源码;内部就是    int类型状态state + 双向链表Node   内部为head->节点->tail尾部    waitStatus节点等待状态,thread那个线程等待,nextWatier下一个等待者  Node prev next  CLH队列先进先出
lock调用cas尝试获取更新state状态 没获取到就加入队列acquire addWaiter加入到队尾 
不公平锁Node都在自旋+cas enq方法内for   tryRelease  LockSupport park阻塞wait unpark相当于notify


并发编程 Thread sleep yiled join interrupt     object 对象都有wait notify notifyAll
Java中线程中状态可分为五种:New(新建状态),Runnable(就绪状态)start,Running(运行状态),Blocked(阻塞状态)(如,I/O操作等)让出CPU执行权,自身进入阻塞状态,Dead(死亡状态)。
不可能从阻塞直接到运行态!!!要先到就绪  Synchronized关键字 配合才能获取到montior的权限
wait()阻塞   wait(long timeout) 
notify和notifyAll的区别在于前者只能唤醒monitor上的一个线程,对其他线程没有影响,而notifyAll则唤醒所有的线程
wait方法依赖于同步,而sleep方法可以直接调用。而更深层次的区别在于sleep方法只是暂时让出CPU的执行权,并不释放锁!!!。而wait方法则需要释放锁。!!!!!!!! sleep静态方法
没有使用join方法之间,线程是并发执行的,而使用join方法后,所有线程是顺序执行的,底层使用wait方法来将线程的阻塞,如果join的线程还在执行,则将当前线程阻塞起来,直到join的线程执行完成,当前线程才能执行
yiled暂停当前线程,以便其他线程有机会执行,不过不能指定暂停的时间,并且也不能保证当前线程马上停止  有可能会被再次执行到的!!!   yield 不会释放对象锁!!!!!
Thread.stop, Thread.suspend, Thread.resume 都已经被废弃了。Thread.interrupt 的作用其实也不是中断线程,而是「通知线程应该中断了」,具体到底中断还是继续运行,应该由被通知的线程自己处理
如果线程处于被阻塞状态,抛出一个InterruptedException异常  如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true   isInterrupted


threadlocal 每个线程都有自己的Thread.ThreadLocalMap中的map  key为这个threadlocal变量  自己维护


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值