并发与高并发

1 并发与高并发基本概念并发:同时拥有两个或者多个线程,如果程序在单核处理器上运行,多个线程将交替地换入或者换出内存,这些线程是同时"存在"的,每个线程都处于执行过程中的某个状态如果运行在多核处理器上,此时程序中每个线程都将分配到一个处理器核上,因此,可以同时运行高并发:是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求.1 CPU缓存...
摘要由CSDN通过智能技术生成

1 并发与高并发基本概念

并发:同时拥有两个或者多个线程,如果程序在单核处理器上运行,多个线程将交替地换入或者换出内存,这些线程是同时"存在"的,每个线程都处于执行过程中的某个状态如果运行在多核处理器上,此时程序中每个线程都将分配到一个处理器核上,因此,可以同时运行
高并发:是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求.

1 CPU缓存

在计算机中,所有的运算操作都是由CPU寄存器来完成的,CPU指令的执行过程需要涉及数据的读取和写入操作,CPU所能访问的所有数据只能是计算机的主存(RAM).由于硬件上面的发展,导致CPU的处理速度和内存的访问速度之间差距越拉越大,由于两边速度严重的不对等,CPU的整体吞吐量降低,于是就有了在CPU和主内存之间增加缓存的设计,缓存的数量可以增加到3级了.CPU Cache又是由很多个Cache line构成的,Cache line是CPU Cache中的最小的缓存单位,目前主流的Cache line大小都是64字节,
Cache的出现是为了解决CPU直接访问内存效率低下问题的,程序在运行过程中,会将运算所需要的数据从主存复制一份到Cache中,这样CPU计算时就可以直接对CPU Cache中的数据进行读取和写入,当运算结束后,再将CPU Cache中的最新数据刷新到主内存中,通过这种方式大大提高了CPU的吞吐能力.

CPU缓存有什么意义

  1. 时间局部性:如果某个数据被访问,那么不久的将来它很可能被再次访问
  2. 空间局部性:如果某个数据被访问,那么与它相邻的数据很快也可能被访问

CPU多级缓存-乱序执行优化
处理器为提高运算速度而做出违背代码原有顺序的优化,单核情况无影响,在多核情况下数据结果可能不一致.

2 CPU缓存一致性

在多线程的情况下,例如i++的操作,多个线程执行共1000次操作,结果很有可能小于10000.解决办法之一是使用缓存一致性协议,最出名的协议为MESI协议,MESI协议保证了每一个缓存中使用的共享变量副本都是一致的,当CPU在操作Cache中的数据时,如果发现该变量是一个共享变量,也就是其他Cache中也存在一个副本,那么:1)读取操作,不过任何处理,知识将Cache中的数据读取到寄存器.2)写入操作,发出信号通知其他CPU将该变量的Cache line置为无效状态,其他CPU在进行该变量读入的时候补得不到主内存中再次获取.

3 PostMan

POSTMAN

编写环境变量
http://localhost:8080可通过{ {}}获取并且访问"/test"地址,这样可以统一环境.更加方便

4 JMeter使用

添加线程组
添加线程组
添加http请求
添加http请求
察看结果树监听
察看结果树监听
图形结果树监听
图形结果树监听

5 线程安全性

1.原子性:同一时刻只能有一个线程访问
2.有序性:禁止指令重排序,保证代码执行顺序
3.可见性:对主内存的修改,其他线程能立即知道.

6 Atomic包

AtomicInteger,AtomicLong等,底层是使用cas来保障数据的原子性

package juc.count;

import juc.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@ThreadSafe
public class CountExample2 {

    // 请求总数
    private static final int clientTotal = 5000;

    // 线程数
    private static final int threadTotal = 50;

    private static AtomicInteger count  = new AtomicInteger(0);

    private static void add(){
        count.incrementAndGet();
    }

    public static void main(String[] args) throws Exception {

        ExecutorService executorService = Executors.newCachedThreadPool();

        //控制最高并发数量
        final Semaphore semaphore = new Semaphore(threadTotal);

        // 控制请求数量
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
        for(int i=0; i < clientTotal; i++) {
            executorService.execute(() -> {
                try {
                    semaphore.acquire();
                    add();
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        log.info("count: {}", count);
        executorService.shutdown();
    }
}

JVM在底层处理long,double计算的时候,会将64位拆成两个32位计算,但是现在的JVM基本都会保证long,double计算的原子性.

LongAdder和DoubleAdder对Atomic进行高并发的优化,缺点是Adder在统计的时候如果有并发更新,可能导致统计的数据有误差。

package juc.count;

import juc.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.LongAdder;

@Slf4j
@ThreadSafe
public class CountExample4 {

    // 请求总数
    private static final int clientTotal = 5000;

    // 线程数
    private static final int threadTotal = 50;

    private static LongAdder count  = new LongAdder();

    private static void add(){
        count.increment();
    }

    public static void main(String[] args) throws Exception {

        ExecutorService executorService = Executors.newCachedThreadPool();

        //控制最高并发数量
        final Semaphore semaphore = new Semaphore(threadTotal);

        // 控制请求数量
        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
        for(int i=0; i < clientTotal; i++) {
            executorService.execute(() -> {
                try {
                    semaphore.acquire();
                    add();
                    semaphore.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        log.info("count: {}", count);
        executorService.shutdown();
    }
}

AtomicReference:以原子读写的对象引用变量

package juc.count;

import juc.annotations.ThreadSafe;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicReference;

@Slf4j
@ThreadSafe
public class CountExample5 {

    // 请求总数
    private static final int clientTotal = 5000;

    // 线程数
    private static final int threadTotal = 50;

    private static AtomicReference<Integer> count  = new AtomicReference(0);

    public static void main(String[] args) throws Exception {
        count.compareAndSet(0,1);
        count.compareAndSet(3,6);
        count.compareAndSet(1,5);
        count.compareAndSet(6,2);
        count.compareAndSet(5,9);
        log.info("success, {}", count);
    }
}

AtomicIntegerFieldUpdater:原子性的更新对象的变量–必须volatile定义

package juc.count;

import juc.annotations.ThreadSafe;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

@Slf4j
@ThreadSafe
public class CountExample6 {

    // 请求总数
    private static final int clientTotal = 5000;

    // 线程数
    private static final int threadTotal = 50;

    private static CountExample6 example6 = new CountExample6();

    //原子性的更新对象的变量--必须volatile定义
    private static AtomicIntegerFieldUpdater<CountExample6> update  = AtomicIntegerFieldUpdater.newUpdater(CountExample6.class, "count");

    @Getter
    private volatile int count = 100;


    public static void main(String[] args) throws Exception {
        if(update.compareAndSet(example6 ,100, 200)){
            log.info("success 1, {}", example6.getCount());
        }
        if(update.compareAndSet(example6 ,100, 300)){
            log.info("success 2, {}", example6.getCount());
        } else {
            log.info("fail, {}", example6.getCount());
        }
    }
}

AtomicStamp

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值