亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

首頁(yè) Java Java面試題 面試官問(wèn)你:你知道什麼是ABA問(wèn)題嗎?

面試官問(wèn)你:你知道什麼是ABA問(wèn)題嗎?

Jul 26, 2023 pm 03:09 PM
cas

貍貓換太子

#在開(kāi)始問(wèn)題的闡述之前,我們先來(lái)看看一則小故事:

北宋宋真宗皇后死後,當(dāng)時(shí)他的兩位愛(ài)妃劉妃和李妃都懷了孕,很顯然,誰(shuí)生了兒子,誰(shuí)就有可能立為正宮。劉妃久懷嫉妒之心,唯恐李妃生了兒子被立為皇后,於是與宮中總管都堂郭槐定計(jì),在接生婆尤氏的配合下,乘李妃分娩時(shí)由於血暈而人事不知之機(jī),將一貍貓剝?nèi)テっ?,血淋淋,光油油地?fù)Q走了剛出世的太子。劉妃命宮女寇珠勒死太子,寇珠於心不忍,暗中將太子交付宦官陳琳,陳琳將太子裝在提盒中送至八賢王處撫養(yǎng)。再說(shuō)真宗看到被剝了皮的貍貓,以為李妃產(chǎn)下了一個(gè)妖物,乃將其貶入冷宮。不久,劉妃臨產(chǎn),生了個(gè)兒子,被立為太子,劉妃也被冊(cè)立為皇后。誰(shuí)知六年後,劉後之子病夭。真宗再無(wú)子嗣,就將其皇兄八賢王之子(實(shí)為當(dāng)年被換走的皇子)收為義子,並立為太子。

從這故事看出來(lái),太子出生被換成了貍貓,最後陰差陽(yáng)錯(cuò)又回歸成為太子。雖然結(jié)果是一樣的,但是過(guò)程曲折了,太子真的是命途多舛啊。

為什麼要說(shuō)這個(gè)故事?其實(shí)跟我們今天要介紹的問(wèn)題有很大的關(guān)係。同樣的結(jié)果,可能中間不知道發(fā)生了多少次操作,那我們能認(rèn)為他沒(méi)改變嗎?在不同的業(yè)務(wù)場(chǎng)景下,我們要仔細(xì)考慮這個(gè)問(wèn)題。

ABA問(wèn)題描述

#在多執(zhí)行緒場(chǎng)景下CAS會(huì)出現(xiàn) ABA問(wèn)題,關(guān)於ABA問(wèn)題這裡簡(jiǎn)單科普下,例如有2個(gè)線程同時(shí)對(duì)同一個(gè)值(初始值為A)進(jìn)行CAS操作,這三個(gè)線程如下:

  1. 執(zhí)行緒1,期望值為A,欲更新的值為B
  2. #執(zhí)行緒2,期望值為A,欲更新的值為B

線程1搶先獲得CPU時(shí)間片,而線程2因?yàn)槠渌蜃枞耍€程1取值與期望的A值比較,發(fā)現(xiàn)相等然後將值更新為B,然後這個(gè)時(shí)候出現(xiàn)了線程3,期望值為B,欲更新的值為A,線程3取值與期望的值B比較,發(fā)現(xiàn)相等則將值更新為A,此時(shí)線程2從阻塞中恢復(fù),並且獲得了CPU時(shí)間片,這時(shí)候線程2取值與期望的值A(chǔ)比較,發(fā)現(xiàn)相等則將值更新為B,雖然線程2也完成了操作,但是線程2並不知道值已經(jīng)經(jīng)過(guò)了A->B->A的變化過(guò)程。

舉個(gè)具體的例子說(shuō)明

#小明在提款機(jī),提取了50元,因?yàn)樘峥顧C(jī)問(wèn)題,有兩個(gè)線程,同時(shí)把餘額從100變成50:

  • #線程1(提款機(jī)):取得目前值100,期望更新為50;
  • 執(zhí)行緒2(提款機(jī)):取得目前值100,期望更新為50;
  • 執(zhí)行緒1成功執(zhí)行,執(zhí)行緒2某種原因block了;
  • 這時(shí),某人給小明匯款50;
  • 線程3(預(yù)設(shè)):取得目前值50,期望更新為100,這時(shí)候線程3成功執(zhí)行,餘額變成100;
  • #線程2從Block恢復(fù),取得到的也是100,compare之後,繼續(xù)更新餘額為50。

此時(shí)可以看到,實(shí)際餘額應(yīng)該是100(100-50 50),但實(shí)際上變成了50(100-50 50 -50)這就是ABA問(wèn)題帶來(lái)錯(cuò)誤提交結(jié)果。

解決方法

#要解決ABA問(wèn)題,可以增加一個(gè)版本號(hào),當(dāng)記憶體位置V的值每次被修改後,版本號(hào)碼都加1

程式碼範(fàn)例

#透過(guò)AtomicStampedReference來(lái)解決ABA問(wèn)題




AtomicStampedReference內(nèi)部維護(hù)了物件值和版本號(hào),在建立AtomicStampedReference物件時(shí),需要傳入初始值和初始版本號(hào);

#當(dāng)AtomicStampedReference設(shè)定物件值時(shí),物件值以及狀態(tài)戳記都必須滿足期望值,寫入才會(huì)成功。


private static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<Integer>(100,1);

public static void main(String[] args) {
//第一個(gè)線程
 new Thread(() -> {
  System.out.println("t1拿到的初始版本號(hào):" + atomicStampedReference.getStamp());
  
  //睡眠1秒,是為了讓t2線程也拿到同樣的初始版本號(hào)
  try {
   TimeUnit.SECONDS.sleep(1);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  atomicStampedReference.compareAndSet(100, 101,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
  atomicStampedReference.compareAndSet(101, 100,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
 },"t1").start();
 
  // 第二個(gè)線程
 new Thread(() -> {
  int stamp = atomicStampedReference.getStamp();
  System.out.println("t2拿到的初始版本號(hào):" + stamp);
  
  //睡眠3秒,是為了讓t1線程完成ABA操作
  try {
   TimeUnit.SECONDS.sleep(3);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  System.out.println("最新版本號(hào):" + atomicStampedReference.getStamp());
  System.out.println(atomicStampedReference.compareAndSet(100, 2019,stamp,atomicStampedReference.getStamp() + 1) + "\t當(dāng)前值:" + atomicStampedReference.getReference());
 },"t2").start();
}


1、初始值100,初始版本號(hào)1

2、執(zhí)行緒t1和t2拿到一樣的初始版本號(hào)
3、執(zhí)行緒t1完成ABA操作,版本號(hào)遞增到3

4、執(zhí)行緒t2完成CAS操作,最新版本號(hào)碼已經(jīng)變成3,跟線程t2之前拿到的版本號(hào)1不相等,操作失敗

###執(zhí)行結(jié)果:######
t1拿到的初始版本號(hào):1
t2拿到的初始版本號(hào):1
最新版本號(hào):3
false 當(dāng)前值:100
################透過(guò)AtomicMarkableReference解決ABA問(wèn)題############# ##AtomicStampedReference###可以為引用加上版本號(hào),追蹤引用的整個(gè)變化過(guò)程,如:A -> B -> C -> D -> A,透過(guò)AtomicStampedReference,我們可以知道,引用變量中途被更改了3次。但是,有時(shí)候,我們並不關(guān)心引用變數(shù)更改了幾次,只是單純的關(guān)心是否更改過(guò),所以就有了###AtomicMarkableReference###, AtomicMarkableReference的唯一差異就是不再用int識(shí)別來(lái)引用,而是使用boolean變數(shù)-表示引用變數(shù)是否被更改過(guò)。 ###
private static AtomicMarkableReference<Integer> atomicMarkableReference = new AtomicMarkableReference<Integer>(100,false);

public static void main(String[] args) {
// 第一個(gè)線程
 new Thread(() -> {
  System.out.println("t1版本號(hào)是否被更改:" + atomicMarkableReference.isMarked());
  
  //睡眠1秒,是為了讓t2線程也拿到同樣的初始版本號(hào)
  try {
   TimeUnit.SECONDS.sleep(1);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  atomicMarkableReference.compareAndSet(100, 101,atomicMarkableReference.isMarked(),true);
  atomicMarkableReference.compareAndSet(101, 100,atomicMarkableReference.isMarked(),true);
 },"t1").start();
 
  // 第二個(gè)線程
 new Thread(() -> {
  boolean isMarked = atomicMarkableReference.isMarked();
  System.out.println("t2版本號(hào)是否被更改:" + isMarked);
  
  //睡眠3秒,是為了讓t1線程完成ABA操作
  try {
   TimeUnit.SECONDS.sleep(3);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  System.out.println("是否更改過(guò):" + atomicMarkableReference.isMarked());
  System.out.println(atomicMarkableReference.compareAndSet(100, 2019,isMarked,true) + "\t當(dāng)前值:" + atomicMarkableReference.getReference());
 },"t2").start();
}
######1、初始值100,初始版本號(hào)未修改false ###2、線程t1和t2拿到一樣的初始版本號(hào)都沒(méi)有被修改false ###3、線程t1完成ABA操作,版本號(hào)碼被修改true ###4、線程t2完成CAS操作,版本號(hào)碼已經(jīng)變成true,跟線程t2之前拿到的版本號(hào)false不相等,操作失敗####### #####執(zhí)行結(jié)果:######
t1版本號(hào)是否被更改:false
t2版本號(hào)是否被更改:false
是否更改過(guò):true
false 當(dāng)前值:100

多說(shuō)幾句

以上是本期關(guān)于CAS領(lǐng)域的一個(gè)經(jīng)典ABA問(wèn)題的解析,不知道你在實(shí)際的工作中有沒(méi)有遇到過(guò),但是在面試中這塊是并發(fā)知識(shí)考查的重點(diǎn)。如果你還沒(méi)接觸過(guò)此類的問(wèn)題,我的建議是你自己將上面的代碼運(yùn)行一下,結(jié)合理論去理解一下ABA問(wèn)題所帶來(lái)的問(wèn)題以及如何解決他,這對(duì)你日后的開(kāi)發(fā)工作也是有莫大的幫助的!

以上是面試官問(wèn)你:你知道什麼是ABA問(wèn)題嗎?的詳細(xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請(qǐng)聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開(kāi)發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)程式碼編輯軟體(SublimeText3)

熱門話題

Laravel 教程
1597
29
PHP教程
1488
72
透過(guò) CAS(Central Authentication Service) 實(shí)現(xiàn) PHP 安全驗(yàn)證 透過(guò) CAS(Central Authentication Service) 實(shí)現(xiàn) PHP 安全驗(yàn)證 Jul 24, 2023 pm 12:49 PM

透過(guò)CAS(CentralAuthenticationService)實(shí)現(xiàn)PHP安全驗(yàn)證隨著網(wǎng)際網(wǎng)路的快速發(fā)展,使用者權(quán)限管理和身分驗(yàn)證越來(lái)越重要。在開(kāi)發(fā)WEB應(yīng)用程式時(shí),保護(hù)使用者資料和防止未經(jīng)授權(quán)存取是至關(guān)重要的。為了實(shí)現(xiàn)這一目標(biāo),我們可以使用CAS(CentralAuthenticationService)來(lái)進(jìn)行PHP的安全驗(yàn)證。 CAS

java CAS的概念是什麼 java CAS的概念是什麼 May 03, 2023 pm 09:34 PM

1.說(shuō)明當(dāng)多個(gè)線程同時(shí)對(duì)某個(gè)資源進(jìn)行CAS操作時(shí),只有一個(gè)線程成功,但不會(huì)堵塞其他線程,其他線程只會(huì)收到操作失敗的訊號(hào)。可見(jiàn)CAS其實(shí)是樂(lè)觀的鎖。 2.實(shí)例跟隨AtomInteger的程式碼,我們可以發(fā)現(xiàn)最終呼叫的是sum.misc.Unsafe。看看Unsafe這個(gè)名字,它是一個(gè)不安全的類別,它利用了Java類別和可見(jiàn)性規(guī)則中恰到好處的漏洞。為了速度,Unsafe在Java的安全標(biāo)準(zhǔn)上做出了一些妥協(xié)。 publicfinalnativebooleancompareAndSwapInt(Objec

java的CAS怎麼應(yīng)用 java的CAS怎麼應(yīng)用 Apr 18, 2023 pm 06:37 PM

CAS解釋:CAS(compareandswap),比較並交換。可以解決多執(zhí)行緒並行情況下使用鎖造成效能損耗的一種機(jī)制。CAS運(yùn)算包含三個(gè)運(yùn)算元—記憶體位置(V)、預(yù)期原值(A)和新值(B)。如果記憶體位置的值與預(yù)期原值相匹配,那麼處理器會(huì)自動(dòng)將該位置值更新為新值。否則,處理器不做任何操作。一個(gè)執(zhí)行緒從主記憶體得到num值,並對(duì)num進(jìn)行操作,寫入值的時(shí)候,執(zhí)行緒會(huì)把第一次取到的num值和主記憶體中num值進(jìn)行比較,如果相等,就會(huì)改變後的num寫入主內(nèi)存,如果不相等,則一直循環(huán)對(duì)比,知道成功為止。 CAS產(chǎn)

CAS與java樂(lè)觀鎖怎麼用 CAS與java樂(lè)觀鎖怎麼用 May 01, 2023 pm 08:07 PM

什麼是CASCAS是CompareAndSwap,即比較和交換。為什麼CAS沒(méi)有用到鎖還能保證並發(fā)情況下安全的操作數(shù)據(jù)呢,名字其實(shí)非常直觀的表明了CAS的原理,具體修改數(shù)據(jù)過(guò)程如下:用CAS操作數(shù)據(jù)時(shí),將數(shù)據(jù)原始值和要修改的值一併傳遞給方法比較當(dāng)前目標(biāo)變數(shù)值與傳進(jìn)去的原始值是否相同如果相同,表示目標(biāo)變數(shù)沒(méi)有被其他執(zhí)行緒修改,直接修改目標(biāo)變數(shù)值即可如果目標(biāo)變數(shù)值與原始值不同,那麼證明目標(biāo)變數(shù)已經(jīng)被其他線程修改過(guò),本次CAS修改失敗從上述過(guò)程可以看到CAS其實(shí)保證的是安全的修改數(shù)據(jù),但是修改存在失敗的

Java有鎖並發(fā)、無(wú)鎖並發(fā)和CAS實(shí)例分析 Java有鎖並發(fā)、無(wú)鎖並發(fā)和CAS實(shí)例分析 May 23, 2023 pm 01:34 PM

有鎖並發(fā)對(duì)於大多數(shù)程式設(shè)計(jì)師(當(dāng)然我也基本上是其中一員),並發(fā)程式幾乎就等價(jià)於為相關(guān)資料結(jié)構(gòu)加上一個(gè)鎖(Mutex)。例如如果我們需要一個(gè)支援並發(fā)的棧,那最簡(jiǎn)單的方法就是給一個(gè)單執(zhí)行緒的棧加上鎖定std::sync::Mutex。 (加上Arc是為了能讓多個(gè)執(zhí)行緒都擁有堆疊的所有權(quán))usestd::sync::{Mutex,Arc};#[derive(Clone)]structConcurrentStack{inner:Arc,}implConcurrentStack{pubfnnew()-> Self{

面試真題:請(qǐng)你聊聊並發(fā)中的CAS 機(jī)制 面試真題:請(qǐng)你聊聊並發(fā)中的CAS 機(jī)制 Jul 26, 2023 pm 03:05 PM

程式中,我創(chuàng)建了100個(gè)線程,每個(gè)線程中對(duì)共享變數(shù)inc進(jìn)行累加10000次的操作,如果是同步執(zhí)行的話,inc最終的值應(yīng)該是1000000,但我們知道在多線程中,程式是並發(fā)執(zhí)行的,也就是說(shuō)不同的執(zhí)行緒可能會(huì)同時(shí)讀取到主記憶體相同的值

面試官問(wèn)你:你知道什麼是ABA問(wèn)題嗎? 面試官問(wèn)你:你知道什麼是ABA問(wèn)題嗎? Jul 26, 2023 pm 03:09 PM

本期關(guān)於CAS領(lǐng)域的一個(gè)經(jīng)典ABA問(wèn)題的解析,不知道你在實(shí)際的工作中有沒(méi)有遇到過(guò),但是在面試中這塊是並發(fā)知識(shí)考查的重點(diǎn)。如果你還沒(méi)接觸過(guò)這類的問(wèn)題,我的建議是你自己將上面的程式碼執(zhí)行一下

基於springboot怎麼搭建CAS Client客戶端 基於springboot怎麼搭建CAS Client客戶端 May 14, 2023 am 10:46 AM

1.新建springboot專案並引入依賴org.jasig.cas.clientcas-client-support-springboot3.6.22.設(shè)定@EnableCasClient註解packagecom.codetiler.demo;importorg.jasig.cas.client.boot.configuration.EnableCasClientimportorg.jasig.cas.client.boot.configuration.EnableCasClientimportorg. springframework.boot.SpringApplication;importorg.spring

See all articles