锁策略,CAS和synchronized的锁优化

  1. 锁策略
  2. synchronized锁优化
  3. CAS锁优化

1.锁策略

乐观锁VS悲观锁

加锁的时候,预测多个线程访问同一个共享变量冲突的概率大还是小

预测当前锁冲突的概率大,就尝试加锁,就是要用悲观锁策略,需要加锁,消耗资源,效率降低

反着就是要用乐观锁,不加锁,在访问的时候才会检测是否会产生所冲突,如果产生并发冲突,就返回错误信息,让用户决定下一步怎么做;不产生锁冲突就不用加锁,效率提高;

synchronized既是悲观锁又是乐观锁

轻量级锁VS重量级锁

指的是加锁的工作的多还是少,加锁的工作多,开销大就是重量级锁,反着就是轻量级锁;乐观锁就是轻量级锁,悲观锁就是重量级锁,两者概念相近,有时混着用,只是出发点不一样;

所以synchronized即使轻量级锁又是重量级锁

自旋锁VS挂起等待锁

自旋锁是轻量级锁的一种典型实现方式,挂起等待锁是重量级锁的一种典型实现方式;

指的是等待线程获取锁的方式不一样,自旋锁是一个while循环一直去访问锁,知道该锁被释放就去尝试获取锁;挂起等待锁是指只要锁已经被其他线程获取,该线程就挂起等待,进入阻塞状态,直到其他线程释放锁,唤醒阻塞的线程,该线程再去尝试获取锁;

以上两种获取锁的方式不同,自旋锁在锁一释放就能就是获取锁,消耗很多CPU资源,但是获取锁的时间快;挂起等待锁,由于被唤醒的时机是不确定的,拿到锁慢,消耗CPU少;

synchronized的轻量级锁部分基于自旋锁实现的,由CAS机制操作;重量级锁部分基于挂起等待锁实现,由系统调用API实现;

公平锁VS非公平锁

指的是所有等待线程获取锁的机会公平与否,如果是按照先来回到的顺序,那么这个锁就是公平锁,如果等待的线程获取锁的概率是均等的,这个锁就是不公平锁,这是由以前发明锁的大佬定义的,如果另一个时间线定义的是是按照概率均等获取锁是公平的,就又是另一个说法;

synchronized是不公平锁,竞争同一个锁的线程获取锁的概率是均等的;

可重入锁VS不可重入锁

可重入锁就是一个线程,针对一个锁,连续加锁两次,不会死锁,会产生死锁就是不可重入锁;

synchronized是可重入锁,c++的stu::mutex是不可重入锁;

互斥锁VS读写锁

互斥锁是一个锁只能同时被一个线程占有,其他线程要获取要等待,synchronized就是典型的互斥锁;

读写锁是分为加读锁,加写锁,解锁,Java中的读写锁是:(1)读锁与读锁之间不会产生互斥;(2)写锁和写锁之间会产生互斥;(3)读锁和写锁之间会产生互斥;降低读锁和读锁的冲突,提高并发能力;

2.synchronized锁优化

锁升级

分为无锁--->偏向锁--->轻量级锁--->重量级锁

某个线程没有锁的是时候就是一个无锁的状态,当这个线程获取到synchnorized时会变成偏向锁,但是不会真正的加锁,只是这个锁会记录目前是哪个线程获取到这个锁,只是做一个标记(不会产生任何的开销,非常快);直到有其他线程要尝试去获取这个锁的时候,就会立即由偏向锁转化成轻量级锁,使得其他线程获取不了这个锁,后续可能会升级会重量级锁,并且这个synchronized只能升级,不能降级;

主打的就是一个“懒”,能不加锁就不加锁,能多慢加锁就多慢加锁,甚至于不加锁,就是下面要谈到的锁消除

锁消除(编译器的优化)

在编译器编译的过程中,会判断该线程是否需要这个锁,如果不需要就会优化掉,消除掉这个锁;举个例子,比如该程序中只有一个线程,就没有必要加锁,编译器就会把锁优化掉;

锁粗化(编译器的优化)

指的是锁的粒度,这个锁要完成的任务越多,代码量越多,粒度就越大;如果一个程序中有多个加锁的细粒度的代码块,编译器会根据情况把他们合并成一个粗粒度的代码;

举个例子就是:你妈妈一会让你出门买个盐,等你回来又让你出门倒个垃圾,等你回来又让你去酱油,上面代指的就是多个细粒度的代码块,而编译器就会把他们都放到一个代码块里面加锁,一次性完成,提高执行效率;

编译器的优化要保证优化前后逻辑要等价才能真正优化;

3.CAS

CAS(compare and swap)就是比较和交换,是一条CPU指令,原子性的指令,完成比较和交换;可以把它想象成一个方法,下面是伪代码:

//如果寄存器1的值与某内存地址的值相等,将寄存器2的值与内存的地址交换
        boolean cas(address,reg1,reg2){
            //更准确来说就是把寄存器2的赋值给内存,后续不关心寄存器2的值
            if(*address==reg1){
                *address=reg2;
                return true;
            }
            return false;
        }

由于CPU提供了上述指令,因此操作系统内核也能够完成上述操作,提供这样的CAS的api,JVM由于对系统的CAS的api进一步封装,在java中也能够使用CAS操作,实际上,被封装在一个“unsafe”的包中,所以不建议直接使用CAS,所以java中有一些类,对CAS进行封装,就是典型的“原子类”;

在java.util.concurrent.atomic中提供了很多原子类,其中AtomicInteger提供了整数++,--的原子性操作,下面示范一下

import java.util.concurrent.atomic.AtomicInteger;

public class demo3 {
    public static void main(String[] args) {
        AtomicInteger count=new AtomicInteger(0);
        //count++
        count.getAndIncrement();
        System.out.println(count);//1
        //++count
        count.incrementAndGet();
        System.out.println(count);//2
        //count--;
        count.getAndDecrement();
        System.out.println(count);//1
        //--count
        count.decrementAndGet();
        System.out.println(count);//0
        //count+=10;
        count.getAndAdd(10);
        System.out.println(count);//10
    }
}

既然是原子类,那么一定是线程安全,下面是多线程的示范

import java.util.concurrent.atomic.AtomicInteger;

public class demo4 {
    private static AtomicInteger count=new AtomicInteger(0);
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    count.incrementAndGet();
                }
            }
        };
        Thread t2=new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 50000; i++) {
                    count.incrementAndGet();
                }
            }
        };
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(count);//10_0000
    }
}

<think>嗯,用户问的是分段CASsynchronized之间的关系。首先,我得确认自己对这些概念的理解是否正确。分段,应该是在并发编程中用来减少竞争的一种技术,比如在Java的ConcurrentHashMap里用到过。CAS是Compare-And-Swap,一种无的原子操作,属于乐观机制。而synchronizedJava中的内置,属于悲观,基于监视器模式。 接下来要思考它们之间的联系。分段可能synchronized有关系,因为分段的实现可能会使用synchronized来同步各个段。而CASsynchronized都是并发控制的手段,但实现方式不同,CAS是无synchronized是阻塞式的。可能需要比较它们的适用场景优缺点。 用户可能是想了解在高并发环境下如何选择这些机制,或者它们如何协同工作。比如,分段通过将数据分块来减少的粒度,CAS用于无的数据结构,synchronized用于更粗粒度的同步。需要解释这三者的不同以及它们如何互补。 要注意结构清晰,分点说明每个概念,再比较它们的关系。可能需要举例子,比如ConcurrentHashMap使用分段CAS结合,而synchronizedJava中用于方法或代码块同步。要确保术语准确,比如CAS属于原子操作,syn是独占,分段分解的一种形式。 还要检查是否有遗漏的关系,比如是否在某些框架或库中这三者会被一起使用。比如,分段结构中的每个段可能使用synchronized,而段内部的操作可能用CAS优化。或者CAS用于状态更新,而分段用于减少的竞争区域。 需要确保回答正确,避免混淆概念。比如,分段属于优化策略CAS属于非阻塞算法,syn是基本的互斥手段。它们都是解决并发问题的方法,但层次方式不同。最后总结它们的优缺点适用场景,帮助用户理解如何选择。</think>好的,我将从概念、原理应用场景逐步解释分段CAS(Compare-and-Swap)synchronized的关系: --- ### 一、基础概念 1. **分段 (Segment Lock)** - 本质:**粒度细化**技术,将共享资源划分为多个独立区块(Segment),每个区块使用独立 - 典型应用:Java的`ConcurrentHashMap`(JDK7实现) - 优点:降低竞争,提升并发度 2. **CAS (Compare-and-Swap)** - 本质:**无编程**的原子操作,通过CPU指令直接实现 - 公式描述:$$ \text{CAS}(V, E, N) = \begin{cases} \text{成功} & \text{if } V == E \\ \text{失败} & \text{otherwise} \end{cases} $$ - 典型应用:`AtomicInteger`、乐观实现 3. **synchronized** - 本质:JVM层面的**悲观**,基于Monitor(监视器)机制 - 特点:自动获取/释放,支持可重入性 --- ### 二、核心关系 #### 1. **分段synchronized** - 组合应用:分段的实现常**以synchronized作为基础单位** - 示例代码: ```java final Segment<K,V>[] segments; // 分段数组 public V put(K key, V value) { Segment<K,V> s = segmentFor(key.hashCode()); synchronized (s) { // 对单个Segment加 // 操作具体Segment } } ``` - 关系本质:分段是**策略**,synchronized是**具体实现手段** #### 2. **分段CAS** - 协同场景:现代并发容器(如JDK8的`ConcurrentHashMap`)**混合使用分段CAS** - 典型模式: - 分段控制整体结构 - CAS操作具体节点(如链表节点的插入) - 优势:既减少竞争,又避免CAS的ABA问题 #### 3. **CASsynchronized** - 对比维度: | 特性 | CAS | synchronized | |---------------------|------------------------|-----------------------| | 类型 | 乐观 | 悲观 | | 阻塞性 | 非阻塞 | 阻塞 | | 实现层级 | CPU指令(如`cmpxchg`) | JVM Monitor | | 适用场景 | 低竞争简单操作 | 高竞争复杂操作 | - 互补关系:在Java并发包中常见**CAS尝试失败后降级为synchronized**(如`LongAdder`实现) --- ### 三、技术演进 1. **历史发展** - 早期:纯synchronized → 性能瓶颈 - 中期:分段 + synchronized → 提升并发度(JDK7) - 现代:分段思想 + CAS + synchronized → 精细化控制(JDK8+) 2. **典型综合应用** - `ConcurrentHashMap`(JDK8): - 使用`Node`数组实现分段结构 - 对头节点使用CAS操作(如`tabAt`/`casTabAt`) - 冲突时降级为`synchronized`单个链表/红黑树 --- ### 四、选择策略 1. **优先CAS**的场景: - 简单原子操作(计数器更新) - 低线程竞争环境 2. **优先分段**的场景: - 大规模结构化数据 - 需要区域性隔离操作 3. **使用synchronized**的场景: - 复杂临界区操作 - 需要等待/通知机制(`wait()`/`notify()`) --- ### 五、总结关系 三者构成并发控制的**多层次解决方案**: - **CAS**提供基础原子操作 - **分段**优化粒度 - **synchronized**作为最终保障手段 它们在不同层级协同工作,共同支撑高性能并发系统。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

a添砖Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值