多线程与高并发编程总结、提升QPS

本文总结了多线程的启动方式,包括new Thread、Runnable和线程池,并探讨了线程的六种状态。深入解析了synchronized与CAS锁的区别,以及volatile的可见性和防止指令重排的作用。文章还介绍了Java中的线程容器,如CopyOnWriteArrayList和BlockingQueue,并提出了提升QPS的策略,包括合理估算线程数、增加连接数和服务无状态等。
摘要由CSDN通过智能技术生成

线程启动的三种方式

1. new Thread().start()

2.new Runnable().start();

3.使用线程池。Executors.newCachedThreadPool()

线程的六种状态

1.new 新建一个线程,未启动。

2.runnable 已经start的线程,等待资源,比如cpu资源。

3.blocked 阻塞状态。等待进入同步代码块锁

4.waiting 。调用了wait(),join(),LockSupport.park() 。 等待重新被唤醒。

5.TIMED_WAITING :sleep、wait(time)、LockSupport.parkUntil(1000)、LockSupport.parkNanos(10000)  知道某个时刻被唤醒。

6.TERMINATED 死亡

 

synchronized 和 CAS锁

cas自旋锁比较占用cpu时间,synchronized不占用cpu,使用的是wait队列。

线程数少使用自旋,否则使用synchronized

synchronized 锁定的是对象而不是代码。重量级锁,直接调用的汇编语言的 lock 命令。

AtomicXXX的类都是使用CAS锁

CAS 锁 :  compareAndSwap等等,都是CPU支持的。

使用CAS锁会存在ABA问题。ABA即,比如甲对丙说我给你买了一瓶农夫山泉,让乙带给你了。路上乙渴了然后喝掉了,去便利店买了一瓶农夫山泉给了丙。农夫山泉还是农夫山泉,但是已经不是甲给的那瓶。

解决ABA问题:加版本号。如果是int类型,基础类型的没什么关系。

AQS 底层就是CAS+ volatile  。关于AQS

volatile 可见性、禁止指令重排,但是不能保证原子性

volatile 通过 MESI (intel cpu协议) 缓存一致性协议  保证多线程可见性。

public class ThreadTest {

    static volatile ThreadTest instance;
    ThreadTest(){
    }

    static ThreadTest getInstance(){
        if(instance == null){
            synchronized (ThreadTest.class){
                if(instance == null){
                    instance = new ThreadTest();
                }
            }
        }
        return instance;
    }

如上单例代码  static volatile ThreadTest instance;  是否需要使用volatile。

必须! 因为 instance = new ThreadTest();  非原子性操作。1.先向内存申请一片 ThreadTest 对象空间 2.对该对象成员变量初始化3.将这块内存赋值给 instance   。 volatile 可以禁止 1、2、3 指令重排。

 

hotspot中正式利用了这一点来区分无锁与偏向锁。无锁与偏向锁的锁状态都为01,但是无锁的biased_lock:表示为0,偏向锁表示为1这就很好的区分了无锁与偏向锁。
无锁------------001
偏向锁-----

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值