这一次手把手带你理解轻量级锁CAS原理

本文通过实现网站访问计数器,演示了线程不安全、Synchronized和原子类(AtomicInteger)在并发场景下的应用。重点介绍了CAS(Compare and Swap)算法,解释其概念、原理,并与Synchronized进行对比。同时,讨论了CAS的CPU开销、不能确保代码块原子性以及ABA问题,并深入探讨了CAS在Java中的底层实现,涉及Unsafe类。最后,通过生活案例进一步阐述ABA问题的潜在风险。
摘要由CSDN通过智能技术生成

一、实现网站访问计数器

1、线程不安全的做法

1.1、代码

复制代码

package com.chentongwei.concurrency;

import static java.lang.Thread.sleep;

/**
 * @Description:
 * @Project concurrency
 */
public class TestCount {

    private static int count;

    public void incrCount() {
        count ++;
    }

    public static void main(String[] args) throws InterruptedException {
        TestCount testCount = new TestCount();
        // 开启五个线程
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                try {
                    sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 每个线程都让count自增100
                for (int j = 0; j < 100; j++) {
                    testCount.incrCount();
                }
            }).start();
        }
        sleep(2000);
        // 正确的情况下会输出500
        System.out.println(count);
    }
}

复制代码

 

1.2、结果

并不一定是500,极大可能小于500。不固定。

1.3、分析

很明显上面那段程序是线程不安全的,为什么线程不安全?因为++操作其实是类似如下的两步骤,如下:

复制代码

count ++;
||
// 获取count
int temp = count;
// 自增count
count = temp + 1;

复制代码

 

很明显是先获取在自增,那么问题来了,我线程A和线程B都读取到了int temp = count;这一步,然后都进行了自增操作,其实这时候就错了因为这时候count丢了1,并发了。所以导致了线程不安全,结果小于等于500。

2、Synchronized保证线程安全

2.1、代码

复制代码

package com.chentongwei.concurrency;

import static java.lang.Thread.sleep;

/**
 * @Description:
 * @Project concurrency
 */
public class TestCount {

    private static int count;

    public  void incrCount() {
        count 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值