并发编程的三大特性之原子性

简介: 并发编程的三大特性之原子性

原子性

这个定义是一种规定,描述了Java中的理想就是为了能实现一个操作不能分割,不可中断,一个线程在执行的时候,另一个线程不会去影响他。

Java中的原子性可以理解为多线程操作临界资源,预期的结果和最终的结果一致。

  • 原子性被破环的演示

如何保证并发编程中的原子性

  • 通过加锁的方式实现

CAS

CAS是compare and swap 是一条CPU级别的并发原语,CAS操作包括三个步骤:比较内存中的值、判断是否相等,如果相等则交换新值;如果不相等,则不做任何操作。这个操作是原子性的,即在执行过程中不会被其他线程中断。

  • 在Java中有使用基于Unsafe类提供关于CAS的操作方法。通过JVM帮助我们实现对CAS操作cpu的汇编指令。
  • CAS 需要注意的是他着重点 是比较和交换 ,值从哪里来需要我们自己获取
  • CAS的最主要应用就是实现乐观锁和锁自旋

CAS操作的时候只能使用对一个变量是原子性的,无法实现对多个

ABA问题:不符合原子操作

  • 解决方案:加入版本号

CAS锁自旋时间过长:

CAS基本都需要自旋,又遇上高并发就会陷入忙等待的状态,进程虽然繁忙但是无法前进

Lock锁

  • Lock是一个接口,我们使用的是他的一些实现类
  • 并发较多的情况下推荐使用ReentrantLock锁
public class Test10 {
    private static int count;
    /**
     * ReentrantLock 是一个对象,使用的时候要把他new出来
     */
    private static ReentrantLock lock = new ReentrantLock();

    public static void increment(){
        lock.lock();
        // 万一出错之后lock之后不会自动释放锁这一点和sy...不一样,需要在finally中释放锁资源
        try {
            count++;
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                increment();
            }
        });
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 100 ; i++) {
                increment();
            }
        });
        thread.start();
        thread2.start();
        thread.join();
        thread2.join();
        System.out.println(count);


    }
}

ReentrantLock可以直接对比synchronized,在功能上来说,都是锁。


但是ReentrantLock的功能性相比synchronized更丰富。


ReentrantLock底层是基于AQS实现的,有一个基于CAS维护的state变量来实现锁的操作。

ThredLocal

  • ThredLocal保证线程安全是不让多线程去操作临界资源
/**
 * @author 舒一笑
 * @date 2023/5/27
 */
public class Test11 {
    static ThreadLocal threadLocal1 = new ThreadLocal();
    static ThreadLocal threadLocal2 = new ThreadLocal();


    public static void main(String[] args) {
        threadLocal1.set("舒一笑");
        threadLocal2.set("每天写代码");
        Thread thread = new Thread(()->{
            System.out.println(threadLocal1.get());
            System.out.println(threadLocal2.get());
        });

        thread.start();

        System.out.println("主线程"+threadLocal1.get());
        System.out.println("主线程"+threadLocal2.get());
    }
}

  • 原理分析

  • 弱引用会被线程回收两头都会回收,key就没有了,所以在使用之后需要remove掉value防止内存泄露

  • 最后完整版应该加上这样两句话
目录
相关文章
|
监控
险境中的智慧航行:ERP系统的风险管理与应对策略
险境中的智慧航行:ERP系统的风险管理与应对策略
1473 5
Idea在debug时打上断点没有用 Skipped breakpoint at ... because it happened inside debugger evaluation
Idea在debug时打上断点没有用 Skipped breakpoint at ... because it happened inside debugger evaluation
2661 0
|
存储 自然语言处理 算法
|
搜索推荐 数据挖掘 API
京东商品评论数据接口(JD.item_review)丨京东API接口指南
京东商品评论数据接口(JD.item_review)丨京东API接口指南
1154 1
|
数据中心
灾难恢复计划
灾难恢复计划
332 4
|
传感器 自动驾驶 安全
自动驾驶中的数据安全和隐私
自动驾驶技术的发展已经改变了我们的出行方式,但伴随着这项技术的普及,数据安全和隐私问题也变得愈发重要。本文将探讨自动驾驶中的数据收集、数据隐私和安全挑战,以及如何保护自动驾驶系统的数据。
631 0
|
设计模式 关系型数据库 Java
顺畅的职责传递-用责任链模式优化决策流程
本文首先通过经典场景展示了不使用设计模式时的问题与痛点。接着,引入责任链模式,详细讲解了其定义、解决问题的方式、结构图及工作原理,并通过重构示例展示了该模式如何解决原有痛点。最后,对责任链模式的优势、缺点以及在实际应用中可能遇到的挑战和限制进行了总结。责任链模式通过解耦请求发送者和接收者,提供了灵活的请求处理机制,适用于多个处理者按顺序处理请求的场景。然而,该模式也可能导致请求得不到处理或性能下降等问题,需在实际应用中权衡利弊。
724 0
顺畅的职责传递-用责任链模式优化决策流程
|
存储 算法 数据可视化
LeetCode 133题详解:广度优先搜索和深度优先搜索实现克隆图
LeetCode 133题详解:广度优先搜索和深度优先搜索实现克隆图
|
负载均衡 算法 druid
SpringBoot 项目如何实现动态配置多数据源?
SpringBoot 项目如何实现动态配置多数据源
969 1
|
iOS开发
iOS本地推送通知的基本使用
简单介绍iOS的本地通知推送的基本使用步骤
1447 0