多线程与高并发(二)

news2024/11/24 4:30:42

【锁的底层实现】:

【 简介 】:

JDK早期的时候是重量级的 , 会去找OS系统申请锁 ,效率非常低。
后来的改进——《锁升级过程》。

【锁升级过程】:

sync( Object )
【偏向锁】:
markword记录这个线程ID( 偏向锁 );如果有线程征用偏向锁的话,这个时候就升级成自旋锁;
【自旋锁】:
自旋锁默认情况下是自旋10次。10次以后升级为重量级锁——去OS中申请资源。
【重量级锁】:
去操作系统申请资源。

【闲聊】:

sync并不比Atmoic原子类的操作慢;

【讨论( 什么情况下使用自旋锁比较合适 )】:

Atomical_Lock用的全都是自旋锁;自旋锁有一个特点,它是占CPU,但是它不访问操作系统,所以它是在用户态去解决问题,它不经过内核态,用户态加锁解锁的效率要比内核态要高。

【 用户态锁 和 内核态锁 比较 】:

内核态不占CPU——在旁边竞争的线程是进入等待队列里,你在那里等着,不占用CPU,什么时候CPU运行了把你叫起来你才运行。
//执行时间长(加锁代码),且线程比较多的用内核态锁( 其它竞争线程可以在等待队列里等待 ),内核态锁即系统锁。
//执行时间短(加锁代码),且线程不是太多。(1个线程执行 ,2W+个线程在自旋 ,效率也是不高的 )。

【day1课后总结】:

  • 线程的概念 、 启动方式 、常用方法。

  • synchronized( Object )
    //不能用String常量 、Integer 、Long

  • 【线程同步】:
    synchronized
    锁的是对象不是代码 ;
    锁this ;
    锁XXX.class ;
    锁定方法和非锁定方法可以同时执行 ;
    锁升级过程:
    偏向锁;
    自旋锁;
    系统锁;
    自旋锁和系统锁各自的使用场景。

【day2课前复习】:

【锁升级 与 对象头】:

对象头上记录着锁升级的全部信息。

【自旋】:

自旋可以看成是一种积极的排队(在那里转圈),是需要占用CPU时间的。

【 Volatile保证线程可见性 】:

【实验】:

package Ten_Class.t02.no122;

import java.util.concurrent.TimeUnit;

public class T {
    /*volatile */ boolean running = true;  //对比一下有无volatile的情况下,整个程序运行结果的区别。

    void  m(){
        System.out.println(  " m start " );

        while (running){   //这里模拟的是服务器的操作~ 服务器如果你不点停止的话,它会一直 7*24小时 一直运行。
            //什么时候running被设置为false , 就立即停止。

//            try{
//                TimeUnit.MILLISECONDS.sleep(10);
//            }catch (InterruptedException e){
//                e.printStackTrace();
//            }
        }
        System.out.println(" m end ! ! ! ");
    }

    public static void main(String[] args) {
        T t = new T();

        new Thread( t::m , "t1" ).start();
        //【 lambda表达式 】:
        //      new Thread( new Runnable(  run(){  m();  }  ) );

        try{
            TimeUnit.SECONDS.sleep(1);
        }catch (InterruptedException e){
            e.printStackTrace();
        }

        t.running = false;
    }
}

【最终输出】:
在这里插入图片描述
//程序一直没有停止!!!

【修改】:

  • 打开volatile
volatile  boolean running = true;  //对比一下有无volatile的情况下,整个程序运行结果的区别。

在这里插入图片描述

【Volatile的两个作用】:

  • 保证线程可见性;
    MESI
    缓存一致性协议

【 Volatile禁止指令重排序 】:

  • 禁止指令重排序;
    DCL单例( Double Check Lock )

【DCL代码】:

package T04_YouXuXing.T05_singleton;

// DCL  Double Check Lock
public class Mgr06 {
    private static volatile Mgr06 INSTANCE;  //JIT

    private Mgr06(){}

    public static Mgr06 getInstance(){
        //业务逻辑代码省略
        if (INSTANCE == null){    //Double  Check  Lock
            synchronized(Mgr06.class) {
                if (INSTANCE==null) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE = new Mgr06();
                }
            }
        }
        return INSTANCE;
    }
    public void m(){
        System.out.println(" m ");
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(
                    ()-> System.out.println(  Mgr06.getInstance().hashCode()  )
            ).start();
        }
    }
}

【本质】:

本质是汇编语言;

【汇编创建对象过程】:

1 )申请空间地址(半初始化)——new
2 )赋值(初始化)——invokespecial
3 )建立关联——astore
在这里插入图片描述
//这里面有指令重排序的话,有可能刚申请了空间,还没有赋值,然后就被赋给了变量。这个时候变量里面是没有值的。
//——超高并发的状态,阿里京东是有可能产生的。

【 Volatile不能保证原子性 】:

package Ten_Class.t02.no124;

import java.util.ArrayList;
import java.util.List;

public class T_加了volatile {
    volatile int count = 0;
    void m(){
        for (int i = 0; i < 10000; i++) {
            count++;
        }
    }

    public static void main(String[] args){
        T_加了volatile t = new T_加了volatile();

        List<Thread> threads = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            threads.add( new Thread( t::m , "thread - "+i ) );
        }

        threads.forEach(o->o.start());

        threads.forEach((o)->{
            try{
                o.join();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        });
        System.out.println( t.count );
    }
}

在这里插入图片描述
//多个线程同时读到这个数,加一之后再写回去,所以浪费了很多机会。
//count这个值是保证了可见性,但是count++这个操作并不是原子性的操作。

【 synchronized优化 】:

//把锁的粒度变细。征用不是特别剧烈的情况下,你的锁的粒度最好要小一些。

【例子】:

m1是错误的 , m2才是正确的。

/**
 * synchronized优化
 * 同步代码块中的语句越少越好
 * 比较m1和m2
 *
 */
package Ten_Class.t02.no125;

import java.util.concurrent.TimeUnit;

public class T_FineCoarseLock {

    int count = 0;

    synchronized void m1() {
        //do sth need not sync
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //业务逻辑中只有下面这句需要sync,这时不应该给整个方法上锁
        count++;

        //do sth need not sync
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    void m2() {
        //do sth need not sync
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //业务逻辑中只有下面这句需要sync,这时不应该给整个方法上锁。
        //采用细粒度的锁,可以使线程争用时间变短,从而提高效率。
        synchronized (this) {
            count++;
        }
        //do sth need not sync。
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

【 锁的粗化 】:

//当征用特别频繁的时候——就应该让锁变大变粗。
在这里插入图片描述
某段业务逻辑中很多很多细碎的小锁,这个时候还不如直接就给弄成一个大锁,它的征用反而就没那么频繁了。

【 final防止对象改变 】:

/**
 * 锁定某对象o,如果o的属性发生改变,不影响锁的使用
 * 但是如果o变成另外一个对象,则锁定的对象发生改变
 * 应该避免将锁定对象的引用变成另外的对象
 *
 * @author mashibing
 */
package Ten_Class.t02.no125;

import java.util.concurrent.TimeUnit;


public class T_SyncSameObject {

    /*final*/ Object o = new Object();

    void m() {
        synchronized (o) {
            while (true) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());


            }
        }
    }

    public static void main(String[] args) {
        T_SyncSameObject t = new T_SyncSameObject();

        new Thread(t::m, "t1").start();

        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Thread t2 = new Thread(t::m, "t2");

        t.o = new Object(); //锁对象发生改变,所以t2线程得以执行,如果注释掉这句话,线程2将永远得不到执行机会
        t2.start();

    }
}

在这里插入图片描述

【day1课程简单回顾】:

【读写屏障】:

  • LoadFence
  • StoreFence

【 CAS(1) 】:

在这里插入图片描述

[ 特殊的类 ]:

由于某些特别常见的操作,需要老是来回加锁;——干脆提供常见操作的类,这些类的内部自动实现了锁,这些锁并不是重量级锁,而是CAS号称无锁,
在这里插入图片描述
//凡是Atomic开头的,都是用CAS来保证线程安全的类。
【例】:

/**
 * 解决同样的问题的更高效的方法,使用AtomXXX类
 * AtomXXX类本身方法都是原子性的,但不能保证多个方法连续调用是原子性的
 *
 * @author mashibing
 */
package Ten_Class.t02.no127;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class T01_AtomicInteger {
	/*volatile*/ //int count1 = 0;

	AtomicInteger count = new AtomicInteger(0);

	/* synchronized */void m() {
		for (int i = 0; i < 10000; i++)
			//if count1.get() < 1000
			count.incrementAndGet(); //count1++
	}

	public static void main(String[] args) {
		T01_AtomicInteger t = new T01_AtomicInteger();

		List<Thread> threads = new ArrayList<Thread>();

		for (int i = 0; i < 100; i++) {
			threads.add(new Thread(t::m, "thread-" + i));
		}

		threads.forEach((o) -> o.start());

		threads.forEach((o) -> {
			try {
				o.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		});

		System.out.println(t.count);
	}
}

【最终输出】:
100000.

【 cas( V , Expected , NewValue ) 】:

cas操作你可以将其想象成一个方法——这个方法有三个参数。
( 1参 ):
要改的那个值。
( 2参 ):
期望当前的值会是多少?
( 3参 ):
要设定的新值。

【 CAS(2) 】:

【 ABA问题 】:

//处理这个问题需要加版本号,加version。
//——用AtomicStampedReference解决ABA问题。
【 ABA问题与数据类型 】:
如果是基础类型,无所谓;
引用类型。

【不需要加锁是怎么做到的呢?】:

  • 内部使用的是Unsafe类。
    在这里插入图片描述
    这个类除了反射能用外,其它的不能直接使用。这个类不能直接使用的原因还和ClassLoader有关系。

【Atomic操作】:

所有的Atomic操作内部下面都是CompareAndSet操作。

【 weakCompareAndSetObject Int Long 】:

//通过名字我们就知道应该是用的指针——软弱虚指针。通过指针的好处就是垃圾回收的时候效率比较高。

【Unsafe】:

直接操纵Java虚拟机里面的那些内存。让我们具备了C++写程序的能力。

【分配/释放 内存】:

【 C 】:
malloc free
【 C++ 】:
new delete

[ CAS ] :

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/89743.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]Python计算机毕业设计Django基于JEE平台springbt技术的订餐系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

以太网 MSTP多实例生成树的简介、MSTP与RSTP、STP之间的联系、MSTP BPDU格式介绍、MSTP关键名词介绍)

2.12.0 以太网 MSTP多实例生成树&#xff08;简介、MSTP与RSTP、STP联系、MSTP BPDU格式、MSTP关键名词介绍&#xff09; 主要参考&#xff1a;华为S2750, S5700, S6700 V200R005(C00&C01&C02&C03) 产品文档 《MSTP基本概念》 MSTP快速生成树简介MSTP关键名词介绍1…

springboot+mybatis+mysql实现的个人博客管理系统(功能包含登录,栏目管理、文章管理、评论管理、系统设置、用户管理、发布博客、评论等)

博客目录springbootmybatis实现的个人博客管理系统实现功能截图系统功能使用技术代码完整源码springbootmybatis实现的个人博客管理系统 本系统是一个个人博客管理系统&#xff0c;比较新的框架springbootmybatis实现&#xff0c;分为普通用户和管理员&#xff0c;普通用户可以…

【软件测试】测试人接手新应用程序怎么测?看看这几个方法......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 应用程序很复杂的&a…

三、数据链路层(三)差错控制

目录 3.1检错编码 3.1.1奇偶校验码 3.1.2循环冗余码&#xff08;CRC&#xff09; 3.2纠错编码 3.2.1海明码 传输差错可分为两种&#xff1a; 位错&#xff1a;帧中某些位出现了差错&#xff0c;也称比特差错、误码。帧错&#xff1a;帧的丢失、重复或失序等错误。 通常利…

面试题:数据结构和算法

1、时间复杂度解释一下 算法的时间复杂度&#xff0c;用来度量算法的运行时间&#xff0c;记作: T(n) O(f(n))。它表示随着 输入大小n 的增大&#xff0c;算法执行需要的时间的增长速度可以用 f(n) 来描述。 当 T(n) c&#xff0c;c 为一个常数的时候&#xff0c;我们说这个…

[附源码]Python计算机毕业设计Django基于vue+mysql开发的考试系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Java web 2022跟学尚硅谷(九)书城项目

Java web 2022跟学尚硅谷九书城项目需求分析数据库设计ER图书城1.0简单部署项目类图相关代码UserControllerUserDAOImplUserDAOBookCartItemOrderOrderItemUserUserServiceImplUserServiceapplicationContext.xml书城1.1实现功能1. 用户登录2. 首页图书列表展示3. 首页价格筛选…

Vue3-ElemenPlu,全栈开发后台系统1-1-2-9第一章,第二章前端系统架构设计

Vue3+ElementPlus Lo2+MongoDB 菜单按钮权限,JWT认证,审批流,常规的CRUD,模块化,组件化 技术栈: 架构设计,vue3全家桶,koa2, 权限: Role-Based A

[附源码]Node.js计算机毕业设计辅导员班级量化管理系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

IMX6启动流程

目录 1. 流程图 2. u-boot.imx的构造 1. 流程图 正常情况下&#xff0c;一台IMX6设备的启动路径就是图中自上而下最左边那条路&#xff1a; 启动/复位后先检查CPU的ID(每颗芯片独一无二) ------> 检查复位状态(有没有按下复位键) ------> 检查boot模式(mmc? USB? SPI…

ARM寄存器组织(常见专用寄存器、控制寄存器CPSR)

目录 一、寄存器的概念 1、什么是寄存器&#xff1f; 2、寄存器的分类 3、不同工作模式下使用的寄存器 二、常见专用寄存器 1、R15&#xff08;PC,Program Counter&#xff09; 2、R14&#xff08;LR,Link Register&#xff09; 3、R13&#xff08;SP,Stack Pointer&am…

FineReport大数据分析工具- 统一切换轮播图表接口

1. 概述 1.1 版本 报表服务器版本 功能变动 11.0 - 1.2 预期效果 某些场景下&#xff0c;需要让一张报表内的多个轮播图表同时切换。那么该如何实现呢&#xff1f;效果如下图所示&#xff1a; 1.3 实现思路 按钮添加点击事件&#xff0c;通过 JS 脚本调用接口统一切换轮播…

【模拟电路】431基准电压源

项目简介 概述 431电压基准芯片为3脚稳压集成电路&#xff0c;431基准电压源具有良好的热稳定性能的&#xff0c;三端可调分流&#xff0c;也被称为电压调解器或三端取样集成电路。凭借体积小、重量轻、精度高、稳定可靠、基准电压精密可调、输出电流大&#xff0c;且价格便宜…

LightDock、PatchDock蛋白蛋白对接软件linux端命令行使用

本文实在ubuntu下操作 DDB1-CRBN.pdb 、brd4.pdb 是需要对接的两个pdb蛋白文件 1、PatchDock 网页版&#xff1a;https://bioinfo3d.cs.tau.ac.il/PatchDock/php.php PatchDock有网页版&#xff0c;如下&#xff1b;软件版需要申请获取下载链接 参考&#xff1a;https://bioi…

QT4.8.7 打开Mupdf

一.Win10环境 1.Win10 Visual Studio 2017 安装 这个直接安装了 a.打开mupdf 源码 b.编译源码 参考这几个贴子 在Qt中调用Mupdf库进行pdf显示 mupdf-1.17.0 源代码编译、下载 qt vc pdf阅读器 我用的是mupdf-1.11-source的&#xff0c;用VS2017打开会有这个问题 c.修改配…

移植MQTT-C库(附源码)

Software (mqtt.org)中mqtt客户端的c库里面有一个叫MQTT-C的库&#xff0c;就2个实现文件&#xff0c;算比较简单的了&#xff0c;实现了基本的mqtt客户端功能&#xff0c;移植一下试试。 我的移植代码放在我的资源里面&#xff1a;https://download.csdn.net/download/oushao…

BigInteger类和BigDecimal类

BigInteger类 BigInteger适合保存比较大的整型 当在编程中遇到需要保存一个特别大的数字&#xff0c;比如地球的人口。 这时如果用long类型保存可能都不够了&#xff0c;此时就需要用到BigInteger BigInteger不能直接*/add()加subtract()减multiply()乘divide()除 使用演示&…

推荐系统学习笔记-论文研读--渐进分层抽取的多任务学习模型

研究背景 多任务相关性的复杂性和竞争性&#xff0c;MTL模型往往会出 现性能退化和负迁移跷跷板现象&#xff0c;即一项任务的性能往往会因影响其他任 务的性能而得到提高 研究成果 跷跷板现象的发现&#xff0c;MTL由于复杂的内在关联性而没有优于相应的单任务模型从联合表…

[附源码]Node.js计算机毕业设计仿咸鱼二手物品交易系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…