Java 高效并发

并发

每秒事物处理数(TPS)

硬件的效率与缓存一致性

Java 高效并发_第1张图片
运算的时候将数据读取到缓存中,让其快速的运算,当运算结束后从缓存进行同步回内存

Java内存模型:
线程共享的变量储存在主内存,每个线程拥有自己的工作内存
注意:局部变量表的引用类型是线程私有的,但是引用指向的对象是线程共享的

volatile修饰符

  1. 保证变量可见性(保证在各个线程的工作内存中是一致的)
  2. 不保证一致性(例如volatile变量a,a++不是原子操作,a++操作在栈顶进行,再写回工作内存,这里缺少同步操作)
  3. 保证此变量不出现指令重排

指令重排

flag=false
....
....
flag=true
....
while(flag){
    ....
}

指令重排出现的问题:究竟循环前面flag=true还是flag=false
不进行指令重排操作:

1.含有锁。
2.final,内联。
3.native c++实现底层。

并发特性

  1. 原子性:原子操作
  2. 可见性:修改立即可见
  3. 有序性:线程内表现串行(线程外无序:指令重排,工作内存和主内存的同步延迟)

先行发生原则

操作A产生的结果会影响到操作B的观察,影响包括:修改共享内存的值,发送了消息,调用了方法等。

a:
i=1

b:
j=i

c:
i=2

a与b操作存在先行发生原则
参考

在没有进行任何同步的情况下,不能在一个线程中对另一个线程的指令执行顺序做任何假设

volatile和synchronized的区别:

volatile效率高,注意使用
synchronized效率不如volatile

线程实现

  1. 使用内核线程(轻量级进程,用户态和核心态来回切换)
  2. 使用用户线程(没有操作系统的支持,所有操作都需要程序处理)
  3. 使用用户线程+轻量级进程混合

Java线程实现

Liunx+Windows线程与轻量级进程一对一

Java线程调度

  1. 协调式进程调度(主动让出cpu,容易由于程序的问题,一直不让出cpu,从而导致系统崩溃)
  2. 抢占式进程调度(被强迫让出cpu)

Java线程五种状态

Java 高效并发_第2张图片
1. 新建(New)
2. 运行(Running)
3. 无限期等待(Waiting)
4. 限期等待(Timed Waiting)
5. 阻塞(Blocked)
6. 结束(Terminated)

线程安全

实现方式:
1. 互斥同步(阻塞同步)synchronized(不公平)+ReentrantLock(可公平)
2. 非阻塞同步(原子操作:失败重试+CAS)
3. 无同步方案(可重入代码+线程本地储存Thread Lock Storage)

锁优化

  1. 自旋锁(时间一定)和自适应自旋锁(时间不一定)
  2. 锁消除(依据变量逃逸情况,决定是否取消锁操作)
  3. 锁粗化(在一系列频繁的反复的上锁和解锁的操作时导致效率低的情况,将锁操作范围扩大)
  4. 轻量级锁(没有竞争的情况下,不使用传统锁,而是用轻量级锁,在没有竞争的情况下高,相反因为多一次CAS操作,不推荐)
  5. 偏向锁(无竞争时去除锁,不推荐)

Lock和synchronized区别比较

转载原处

  1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;

  2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;

  3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;

  4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。

  5)Lock可以提高多个线程进行读操作的效率。

  在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择

Interrupt()方法

只能中断阻塞状态的线程,而不能中断运行中的线程。

你可能感兴趣的:(Java基础)