栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

多线程与高并发(一)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

多线程与高并发(一)

基础概念(本章)

JUC同步工具(本章)

同步容器(后续)

线程池(后续)

高频面试和加分项(后续)

Disruptor  mq框架,单机性能最高,效率最好(后续)

个人学习记录,不喜勿喷


day1

线程概念,常用方法,线程状态

synchronized(Object)

不能用String常量,Integer(值变了,就会变一个新对象) Long

"object"

String常量,所有用到都是同一个,假如都是一个类库的,不同的代码会是用的一把锁,死锁。

Object=null时能当锁么?编译不过,空指针异常

线程同步 -synchronized

.锁的是对象(类的前两位)不是代码

.thie  Object.class

.锁定方法  非锁定方法,可以同时执行

.异常对同步块的影响

抛出异常会释放锁,会导致数据不一致,使用catch包裹可避免。

.锁升级

synchroized的底层实现:

早期JDK: 重量级:OS找操作系统去申请锁;

改进1.5之后:  锁升级的概念---我就是厕所所长

sync(object)

markword  对象头上前两位记录锁的类型,还记录这个线程ID  (偏向锁)

如果有线程争用 : 升级为  自旋锁(占用CPU但不占用资源)

自循环while,10次后升级为重量级锁-OS

升级后,大多数情况下效率是很好的

只能升级,无法降级。两个线程都升级为OS之后,降到自旋锁效率会更高,但是降不下来了。

系统锁什么时候比自旋锁效率高?

执行时间长,线程数量少。反之自旋锁效率高

lock             :CAS 一直自旋,会占用cpu

synchroized :升级到OS之后,会进入wait队列,不占用cpu时间

day2 控制大对象

XX:PretenureSizeThreshold 默认值和作用

超过这个值对象直接在old区分配内存

默认值始0,意思是不管多大都先在eden中分配内存

volatile .保持线程的可见性

线程执行时,会产生副本,修改自身副本里的内容,读取中会被别人线程修改,导致值丧失一致性

加volatile之后,没次写都会被线程读到

- MESI - cpu缓存一致性协议 .禁止指令重排序(cpu)

并发执行指令,编译器把指令重新排序。汇编语言的重排序

-DCL单例

保证在JVM内存中,永远只有某一个类的一个实例。例如:权限

.饿汉式
private static Object ob = new Object();

pulic static  Object getOb(){
    return this.ob ;
}

static保证只有一个实例,JVM做初始化。

不使用的时候会被实例化,要求使用的时候初始化

.懒汉式
private static Object ob;

pulic static  Object getOb(){
    if(ob==null){
       tob = new Object ();
    }
    return this.ob ;
}

多线程会出现问题,需要线程安全

.懒汉式+方法锁

get的时候添加synchroized

private static Object ob;

pulic static  Object  synchroized   getOb(){
    if(ob==null){
       tob = new Object ();
    }
    return this.ob ;
}

锁在方法上,方法实现如果太多代价太重了

.懒汉式+代码块锁

在实例化的时候添加synchroized 块

private static Object ob;

pulic static  Object  getOb(){
    if(ob==null){
        synchroized(this){
          tob = new Object();
        }   
    }
    return this.ob ;
}

仍有问题,多线程下为空时,会发生在同步块中同时new。

.双重检查

第一重判空的必要性:不申请锁,提高效率,多数情况下是不为空的。

private static Object ob;

pulic static  Object  getOb(){
    if(ob==null){
        synchroized(this){
            if(ob==null){
              tob = new Object();
            }
        }   
    }
    return this.ob ;
}

很难复现,但依然会出现问题,问题出现在指令重排序上。ASM在三个指令码之间设置睡眠

-Double Check Lock .双重检查+volatile 
private static volatile Object ob;

pulic static  Object  getOb(){
    if(ob==null){
        synchroized(this){
            if(ob==null){
              tob = new Object();
            }
        }   
    }
    return this.ob ;
}

创建对象JVm三个步骤

1,给这个对象申请内存                  :a=0

2,给这个对象的成员变量初始化     :a=8

3,把这块内存的内容分配给这个对象  :栈内存指向a=8的地址

如果发生指令重排序,二三步颠倒了,半初始化的时候就赋值了,会发生还没有初始化的时候就把指向指定到a=0的地址,这个对象就不为空了,多线程读取的值是不同的。

相当于把半成品发布,虽然这个半成品会逐渐完善,但这个过程中充满了不确定。

帮助开阔思路,理解虚拟机。实际工作中直接用饿汉式,不会差那么一个对象的内存。

synchroized 保证原子性,但是不能阻止重排序。

volatile 并不能保证多个线程共同修改变量时锁带来的不一致问题,都看到是同一个,但会同时做一样的事情,没有原子控制,多人做了重复的事情。(案例:多线程不用同步,操作一个volatile 修饰的变量。在操作方法上添加同步可以解决)

synchroized ZED优化

细化:业务逻辑中,sync加在具体 操作资源上,而不是整个方法;

粗化:业务逻辑中有多个块锁,整合在一起,减少系统征用。(查询数据库表时,每一行都加锁,不如加在表上)

锁定义时,如果发生改变,影响锁的使用

锁是锁定对象额头两位,锁本身发生变化时,会影响锁的使用。解决办法是添加final关键字

 

volatile int[] 当做锁,数组发生变化时,对锁的影响

-Mgr06.java

查看字节码视图

 打开idea 中的settings > plugins 搜索 jclasslib Bytecode  Viewer 插件 安装重启生效

view  -  Show Bytecode With jclasslib  -

public static void main(String argv[]){
    T t =   new T();
    t.setA(8);
}

 0 new #2
 3 dup
 4 invokespecial #3 >
 7 astore_1
 8 aload_1
 9 bipush 8
11 invokevirtual #4
14 return

- loadfence原语指令 ,storefence原语指令

读写屏障

CAS(无锁(乐观锁)优化 自旋)

AtomXXX类

AtomicInteger

int类型的原子性操作,不用添加sync和volatile

.Compare  And Set

比较和设置

.cas(V,Expected,NewValue)

当前值是我期望的值,操作该值。我设置的时候没人改变他的值,他是我期望的时候操作。
 

cas(V,期望值,更新值){
    Expected  = read v;

    for(;;){

       if V == Expected 
            V=NEW
       else
           不是期望的值,需要重新读取
     }
}

OTHERWISE TRY AGAIN OR FAIL

-CPU原语支持

cpu指令级别,不能被打断

ABA问题

先把1变成2,然后变成1。版本号

基础类型没问题,如果是引用就会有问题。object,对象的引用被改变,实际地址就改变了。(女朋友跟你复合,中间经历了别的女人,指针发生变化了?)

A 1.0

B 2.0

A 3.0

AtomicStampedReference 

Unsafe (恶汉单例)

不能直接使用,只能在反射的时候使用(8,11可以使用)。

使用了弱指针的优势,垃圾回收的时候效率高。

操作内存,具备了C++的能力。

分配释放内存

allocateMemory freeMemory     - >   c  malloc free      - >  c++ new delete

Unsafe = c  c++的指针 

day3 JUC同步工具 LongAdder  >  Atomic >  sync  高并发下效率高

Atomic >  sync

CAS(无锁(乐观锁)优化 自旋)

线程多,操作时间短的情况下,自旋锁大于系统锁的性能

LongAdder  >  Atomic 

CAS(无锁(乐观锁)优化 自旋)的基础上

内部分段:例如1000个线程,分成4个250个线程在一起工作,然后把这个4个一加。

线程数特别多,有明显优势。

LOCK   -可重入锁

可重入锁:锁一次后,可以对同样的锁再锁一次 。线程1获得锁,当线程1执行完任务再次进入的时候,在锁的头上记录有线程的标识号,对比后发现一致,继续执行,不需要额外申请。

子类实现调用父类。

sync  m1 {}
sync  m2 {}

new Thread(rl:m1).startt();
new Thread(rl:m2).startt();

//这时1先拿到锁,2永远最后执行

//但是如果在1里面调用2,两个方法都可以执行。

sync  方法 == sync(this) 是同一把锁

.reentrantLock

使用reentrantLock 重写例子,与sync 不同的是,需要在finally里解锁

.tryLock 尝试申请时间

在指定之间内,尝试获取锁

.lockInterruptibly 可以对interrput()方法做出响应

sync

一旦wait之后,必须notify才能醒来。

lock

可以被打断的加锁,使用interrput(),可以打断加锁

---todo

.公平锁
new ReentrantLock(true);

谁等待在前面,谁先执行。而不是一起抢。就是排不排队

先到得线程在等待队列中,公平锁:新来的线程会查看队列中是否有线程,如果有,进入队列等待;非公平锁:新来的线程直接抢锁是可能抢到得。

不是绝对的公平,只是先取队列中的。你还没排队,我买完东西后,又排队了。

.ReentrantLock  vs  sync

锁的类型·

trylock

lockInterruptibly

公平和非公平

.CountDownLatch

倒数的门栓:等待结束

await();//阻塞

countDown();//-1,本身是原子的

也可以使用join

.CyclicBarrier

循环栅栏:

CyclicBarrier cb = new CyclicBarrier (20,new Runnable(){

run(){

满20人,发车

}})

CyclicBarrier cb = new CyclicBarrier (20,()-> );

cb.await();//加人

读取数据场景

数据库,网络,文件必须都读到才能执行,

顺序执行太慢,并发执行并使用CyclicBarrier大大节约执行时间。

使用时间比较:1+2+3      1,2,3里最长的

.Guava RateLimiter

场景:限流

.MarriagePhaser 1.7

arriveAndAwaitAdvance();//等待到达

arriveAndAwaitderegistert();//阶段停止

按不同的阶段执行:分阶段执行,需要多个参与的。(遗传算法)

循环栅栏,多个关卡,每个关卡的线程数。

场景:结婚  到达,吃,离开,洞房

不同的人有不同的阶段

所有人到才能开席,新浪新娘才能洞房

.ReasWiriteLock

读(共享)写(排他,互斥)锁

读多,写少,保证数据的一致性。读写都需要加锁,避免脏读。

.Semaphore  信号灯

限流,同时只允许多少个线程执行。高速口,5个收费窗口

线程执行去获取锁,才能执行。限制的不是多少线程,而是限制多少线程同时执行。

公平,非公平

.Exchange

交换器,两个线程交换数据使用。阻塞交换,继续执行。

多个阻塞再两两交换。

游戏中交换装备,DNF交易

乐关锁:aqs,悲观锁:sync  ,自旋锁:aqs,读写锁(排它锁,共享锁):lock,分段锁:ConcurrentHashMap,Segment

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/353548.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号