>  기사  >  Java  >  초보자도 BAT 면접관과 경쟁할 수 있습니다: CAS

초보자도 BAT 면접관과 경쟁할 수 있습니다: CAS

Java后端技术全栈
Java后端技术全栈앞으로
2023-08-24 15:09:211426검색

머리말

Java 동시 프로그래밍 시리즈의 추가 부분C A S(비교 및 교환), 기사 스타일은 여전히 ​​이해하기 쉬운 그림과 텍스트로 가득 차 있어 독자가 면접관과 미친 대화를 나눌 수 있습니다. C A S(Compare and swap),文章风格依然是图文并茂,通俗易懂,让读者们也能与面试官疯狂对线。

C A S作为并发编程必不可少的基础知识,面试时C A S也是个高频考点,所以说C A S是必知必会,本文将带读者们深入理解C A S

C A S code>동시 프로그래밍에 대한 필수적인 기본 지식으로 인터뷰 시<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px; 여백 왼쪽: 2px;배경 색상: rgba(27, 31, 35, 0.05); 글꼴 계열: " operator mono consolas monaco menlo monospace break-all rgb>C A S도 고주파 테스트 사이트이므로 C A S는 꼭 알아야 할 내용이며, 이 기사는 독자들에게 심층적인 이해를 제공할 것입니다.C A S. 🎜

개요

초보자도 BAT 면접관과 경쟁할 수 있습니다: CAS

CA S의 기본 개념

C A S(compareAndSwap)也叫比较交换,是一种无锁原子算法,映射到操作系统就是一条cmpxchg硬件汇编指令(保证原子性),其作用是让C P U将内存值更新为新值,但是有个条件,内存值必须与期望值相同,并且C A S작업은 사용자 모드와 커널 모드 간 전환이 필요하지 않으며, 사용자 모드에서 직접 메모리를 읽고 씁니다(블로킹/스레드가 없음을 의미). 컨텍스트 전환).

它包含3个参数<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px; background-color : rgba(27, 31, 35, 0.05); 글꼴 계열: " operator mono consolas monaco menlo monospace break-all rgb> C A S(V,E,N)V表示待更新的内存值,E表示预期值,N表示新值,当 V值等于E值时,才会将V值更新成N值,如果V值和E值不等,不做更新,这就是一次C A S적 작업。3个参数C A S(V,E,N)V表示待更新的内存值,E表示预期值,N表示新值,当 V值等于E值时,才会将V值更新成N值,如果V值和E值不等,不做更新,这就是一次C A S的操作。

초보자도 BAT 면접관과 경쟁할 수 있습니다: CAS

简单说,C A S

초보자도 BAT 면접관과 경쟁할 수 있습니다: CAS

简单说,C A S외부 발행은 个期望值, 也就是你认为这个变weight现에서 应该是什么样子의, 如果变weight는 不是你想象的那样,说明它已经被别人修改过了,你只需要重新读取,设置新期望值,再次尝试修改就好了。🎜

C A S가 원자성을 보장하는 방법

원자성은 하나 이상의 작업이 C P U 실행 중에 중단할 수 없는 기능입니다. 실행되거나 실행되지 않으며 중간에 실행할 수 없습니다(중단될 수 없는 기능입니다) 또는 일련의 작업). C P U执行的过程中不被中断的特性,要么执行,要不执行,不能执行到一半(不可被中断的一个或一系列操作)。

为了保证C A S的原子性,C P U提供了下面两种方式

  • 总线锁定
  • 缓存锁定

总线锁定

总线(B U S)是计算机组件间的传输数据方式,也就是说C P U与其他组件连接传输数据,就是靠总线完成的,比如C P U

rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 100, 65);">C A S 의 원자성, C PU는 다음 두 가지 방법을 제공합니다🎜
  • 버스 잠금 장치
  • 캐시 잠금
  • ul>

    🎜🎜버스 잠금🎜 🎜 🎜

    🎜버스(B U S)는 컴퓨터 구성 요소 간에 데이터를 전송하는 방법입니다. 즉, C P U는 다른 구성 요소와 연결하여 데이터를 전송합니다. 이는 C P U는 메모리를 읽고 씁니다. 🎜
    초보자도 BAT 면접관과 경쟁할 수 있습니다: CAS

    总线锁定是指C P U使用了总线锁,所谓总线锁就是使用C P ULOCK#信号,当C P U에서 总线上输流LOCK#信号时,其他C P U적总线请求将被阻塞。C P U使用了总线锁,所谓总线锁就是使用C P U提供的LOCK#信号,当C P U在总线上输出LOCK#信号时,其他C P U的总线请求将被阻塞。

    초보자도 BAT 면접관과 경쟁할 수 있습니다: CAS

    缓存锁定

    总线锁定方式虽然保证了原子性,但是在锁定期间,会导致大量阻塞,增加系统的性能开销,所以现代C P U为了提升性能,通过锁定范围缩小的思想设计出了缓存行锁定(缓存行是C P U초보자도 BAT 면접관과 경쟁할 수 있습니다: CAS

    缓存锁결정

    🎜总线锁定方式虽然保证了原子性,但是在锁定期间,会导致大weight阻塞,增加系统的性能开销,所以现代C P U为了提升性能,通过锁定范围缩작은思想设计了缓存行锁定(🎜缓存行是C P U高速缓存存储的最小单位🎜)。🎜

    소위 캐시 잠금C PUC P U缓存行进行锁定,当缓存行中的共享变量回写到内存时,其他C P U会通过总线嗅探机制感知该共享变量是否发生变化,如果发生变化,让自己对应的共享变量缓存行失效,重新从内存读取最新的数据,缓存锁定是基于缓存一致性机制来实现的,因为缓存一致性机制会阻止两个以上C P U同时修改同一个共享变量(现代C P U基本都支持和使用缓存锁定机制)。

    C A S的问题

    C A S和锁都解决了原子性问题,和锁相比没有阻塞、线程上下文你切换、死锁,所以C A S要比锁拥有更优越的性能,但是C A S同样存在缺点。

    C A S캐시 라인

    을 잠그고, 캐시 라인의 공유 변수가 메모리에 다시 기록되면 다른C P U는 버스 스니핑 메커니즘을 통해 공유 변수가 변경되었는지 여부를 감지합니다. 해당 공유 변수 캐시 라인이 유효하지 않으며 최신 데이터를 메모리에서 다시 읽습니다. 캐시 잠금은 캐시 일관성 메커니즘을 기반으로 구현됩니다. 캐시 일관성 메커니즘은 두 개 이상의 C P U동일한 공유 변수를 동시에 수정 (🎜ModernC P U기본적으로 모두 캐시 잠금 메커니즘을 지원하고 사용합니다 🎜). 🎜<h1 data-tool="mdnice editor" style="margin-top: 30px;margin-bottom: 15px;font-weight:bold;font-size: 24px;"> <span style="display: none; "></span>C A S 문제</h1>🎜<code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px; margin- 왼쪽: 2px;배경색상: rgba(27, 31, 35, 0.05);글꼴군: " operator mono consolas monaco menlo monospace break-all rgb>C A S 및 잠금은 둘 다 원자성 문제를 해결합니다. 잠금에 비해 차단, 스레드 컨텍스트 전환 및 교착 상태가 없으므로 C A S는 잠금보다 성능이 우수하지만C A S동일 단점이 있습니다. 🎜🎜C A S 코드의 문제점은 다음과 같습니다🎜<ul class="list-paddingleft-2" data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;list-style-type: square;"> <li><section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"><strong style="color: black;">공유 변수의 원자적 연산만 보장할 수 있습니다</strong></section></li> <li><section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"><strong style="color: black;">스핀 시간이 너무 깁니다(스핀 잠금 기준)</strong></section></li> <li><section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"><strong style="color: black;"><code style="overflow-wrap: break -word ;패딩: 2px 4px;테두리 반경: 4px;마진-오른쪽: 2px;마진-왼쪽: 2px;배경색: rgba(27, 31, 35, 0.05);글꼴 계열: " operator mono consolas monospace break-all rgb>ABAQuestionABA问题

只能保证一个共享变量原子操作

C A S只能针对一个共享变量使用,如果多个共享变量就只能使用锁了,当然如果你有办法把多个变量整成一个变量,利用C A S也不错,例如读写锁中state

🎜

단 하나의 공유 변수만 원자적 작업을 보장할 수 있습니다.

C A S는 하나의 공유변수에만 사용할 수 있습니다. 공유변수가 여러 개인 경우에는 잠금만 사용할 수 있습니다. 물론, C A S도 좋습니다(예: 읽기-쓰기 잠금상태의 상위 및 하위 비트. 🎜

스핀 시간이 너무 깁니다

스레드가 잠금 획득에 실패하면 차단 및 일시 중단되지 않고 성공할 때까지 일정 시간 후에 다시 획득을 시도합니다. 일종의 루프 획득 메커니즘을 스핀 잠금이라고 합니다(스핀락). spinlock)。

自旋锁好处是,持有锁的线程在短时间内释放锁,那些等待竞争锁的线程就不需进入阻塞状态(无需线程上下文切换/无需用户态与内核态切换),它们只需要等一等(自旋),等到持有锁的线程释放锁之后即可获取,这样就避免了用户态和内核态的切换消耗。

自旋锁坏处显而易见,线程在长时间内持有锁,等待竞争锁的线程一直自旋,即CPU一直空转,资源浪费在毫无意义的地方,所以一般会限制自旋次数。

最后来说自旋锁的实现,实现自旋锁可以基于C A S实现,先定义lockValue对象默认值11代表锁资源空闲,0

스핀 잠금의 장점은 잠금을 보유하고 있는 스레드가 짧은 시간에 잠금을 해제하고, 경쟁 잠금을 기다리는 스레드는 차단 상태에 들어갈 필요가 없다는 것입니다. 사용자 모드 및 커널 모드 전환), 잠금을 보유하고 있는 스레드가 잠금을 획득하기 전에 잠금을 해제할 때까지 기다려야(🎜spin)하므로 사용자 모드와 커널 모드 사이를 전환하는 소비를 방지할 수 있습니다. 커널 모드. 🎜🎜스핀 잠금의 단점은 명백합니다. 스레드가 잠금을 오랫동안 보유하고 경쟁 잠금을 기다리는 스레드가 계속 회전합니다. 즉, CPU가 계속 유휴 상태가 되어 의미 없는 곳에 리소스가 낭비되므로 일반적으로 스핀 수가 제한된. 🎜🎜마지막으로 스핀 잠금 구현에 대해 이야기하겠습니다. C A S 구현, 먼저 lockValue객체 기본값1,1은 잠금 리소스가 사용 가능함을 의미합니다. 0은 잠금 리소스가 사용 중임을 의미하며 코드는 다음과 같습니다🎜
public class SpinLock {
    
    //lockValue 默认值1
    private AtomicInteger lockValue = new AtomicInteger(1);
    
    //自旋获取锁
    public void lock(){

        // 循环检测尝试获取锁
        while (!tryLock()){
            // 空转
        }

    }
    
    //获取锁
    public boolean tryLock(){
        // 期望值1,更新值0,更新成功返回true,更新失败返回false
        return lockValue.compareAndSet(1,0);
    }
    
    //释放锁
    public void unLock(){
        if(!lockValue.compareAndSet(1,0)){
            throw new RuntimeException("释放锁失败");
        }
    }

}

AtomicInteger类型的lockValue变量,AtomicIntegerJava基于C A S实现的Integer原子操作类,还定义了3个函数lock、tryLock、unLock

tryLock 함수는 위에 정의되어 있습니다 - 잠금을 획득하세요

  • 期望值1,更新值0
  • C A S更NewC A S更新
  • 如果期望值与lockValue值相等,则lockValue值更新为0,返回true,否则执行下面逻辑
  • 如果期望值与lockValue值不相等,不做任何更新,返回false

如果期望值与lockValue值上等,则lockValue值更新为0,返回 true,否则执行下面逻辑

🎜🎜🎜🎜🎜如果期望值与lockValue值不任何更新,返回거짓🎜🎜🎜🎜🎜unLock函数-释放锁🎜
  • 期望值0, 새로운 버전10,更新值1
  • C A S更新
  • 如果期望值与lockValue值相等,则lockValue值更新为1,返回true,否则执行下面逻辑
  • 如果期望值与lockValue值不相等,不做任何更新,返回false

C A S更新

🎜🎜 🎜🎜🎜如果期望值与lockValue值상等,则lockValue值更新为1 ,返回true ,否则执行下면逻辑🎜🎜🎜🎜 🎜🎜如果期望值与lockValue值不상等, 不做任何更新,返回false🎜🎜🎜🎜🎜lock函数-自旋获取锁🎜<ul class="list-paddingleft-2" data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;list-style-type: square;"><li><section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"><strong style="color: black;">실행<code style='overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 100, 65);'>tryLock函数,返回true停止,否则一直循环
초보자도 BAT 면접관과 경쟁할 수 있습니다: CAS

从上图可以看出,只有tryLock成功的线程(lockValue更新为0),才会执行代码块,其他线程个tryLock自旋等待lockValue被更新成1tryLock成功的线程执行unLocklockValue更新为1),自旋的线程才会tryLock성공했습니다.

ABA 문제

C A S需要检查待更新的内存值有没有被修改,如果没有则更新,但是存在这样一种情况,如果一个值原来是A,变成了B,然后又变成了A,在C A S확인해 보면 수정되지 않은 것을 확인할 수 있습니다.

쓰레드가 2개 있다고 가정하면, 쓰레드1读取到内存值A,线程1时间片用完,切换到线程2,线程2也读取到了内存值A,并把它修改为B值,然后再把B值还原到A值,简单说,修改次序是A->B->A,接着线程1恢复运行,它发现内存值还是A,然后执行C A S操作,这就是著名的ABA가 문제지만 문제는 없는 것 같습니다.

단순한 데이터 구조이므로 실제로는 문제가 없습니다. 복잡한 데이터 구조라면 문제가 있을 수 있습니다. (AtomicReference可以把C A S使用在对象上),以链表数据结构为例,两个线程通过C A S去删除头节点,假设现在链表有A->B노드

를 사용하세요.)
초보자도 BAT 면접관과 경쟁할 수 있습니다: CAS
  • 线程1删除A节点,B节点成为头节点, 正要执行C A S(A,A,B) 时,时间文 完,切换到线程 21删除A节点,B节点成为头节点,正要执行C A S(A,A,B)时,时间片用完,切换到线程2
  • 线程2删除A、B节点
  • 线程2加入C、A节点,链表节点变成A->C
  • 线程1重新获取时间片,执行C A S(A,A,B)
  • 丢失C
  • 🎜线程2 删除A、B节点🎜🎜🎜🎜线程2加入C、A节点,链表节点变成A->C 코드>🎜🎜🎜🎜线程1 새로 추가된 获取时间 Images 执行C A S(A, A,B)🎜🎜🎜🎜丢失C节点🎜🎜

해결하려면A B A问题也非常简单,只要追加版本号即可,每次改变时加1,即A —> B —> A,变成1A —> 2B —> 3A,在Java中提供了AtomicStampedRdference可以实现这个方案(面试只要问了C A S,就一定会问ABA 이것을 이해해야 합니다).

위 내용은 초보자도 BAT 면접관과 경쟁할 수 있습니다: CAS의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 Java后端技术全栈에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제