Java?synchornized與ReentrantLock處理并發(fā)出現(xiàn)的錯(cuò)誤
什么是并發(fā)錯(cuò)誤
多個(gè)線程共享操作同一個(gè)對(duì)象的時(shí)候,線程體當(dāng)中連續(xù)的多行操作未必能夠連續(xù)執(zhí)行 很可能操作只完成了一部分,時(shí)間片突然耗盡,此時(shí),另一個(gè)線程搶到時(shí)間片,直接拿走并訪問(wèn)了操作不完整的數(shù)據(jù)(操作不完整的數(shù)據(jù),從邏輯上講是錯(cuò)誤數(shù)據(jù))。
并發(fā)錯(cuò)誤是如何產(chǎn)生的
根本原因: 多個(gè)線程共享操作同一份數(shù)據(jù)
直接原因: 線程體當(dāng)中連續(xù)的多行語(yǔ)句,未必能夠連續(xù)執(zhí)行,很可能操作只完成了一半 時(shí)間片突然耗盡。
此時(shí)另一個(gè)線程剛好搶到時(shí)間片,直接拿走了操作不完整的數(shù)據(jù) - 錯(cuò)誤數(shù)據(jù)。
導(dǎo)火索: 時(shí)間片突然耗盡
演示并發(fā)錯(cuò)誤
public class TestConcurrentError{
public static void main(String[] args){
Student stu = new Student("張朝偉","先生");
PrintThread pt = new PrintThread(stu);
ChangeThread ct = new ChangeThread(stu);
pt.start();
ct.start();
}
}
class PrintThread extends Thread{
Student stu;
public PrintThread(Student stu){
this.stu = stu;
}
@Override
public void run(){
while(true){
System.out.println(stu);
}
}
}
class ChangeThread extends Thread{
Student stu;
public ChangeThread(Student stu){
this.stu = stu;
}
@Override
public void run(){
boolean isOkay = true;
while(true){
if(isOkay){
stu.name = "張曼玉";
stu.gender = "女士";
}else{
stu.name = "梁朝偉";
stu.gender = "先生";
}
isOkay = !isOkay;
}
}
}
class Student{
String name;
String gender;//性別
public Student(String name,String gender){
this.name = name;
this.gender = gender;
}
@Override
public String toString(){
return name + " : " + gender;
}
}
我們看運(yùn)行結(jié)果發(fā)現(xiàn)一個(gè)非常嚴(yán)重的問(wèn)題

我們的代碼從來(lái)沒(méi)有寫(xiě)過(guò)將梁朝偉賦值為女士,也沒(méi)有寫(xiě)過(guò)將張曼玉賦值為女士我們的程序?yàn)槭裁磿?huì)出現(xiàn)這樣的情況 ?
線程體當(dāng)中連續(xù)的多行操作未必能夠連續(xù)執(zhí)行 假如我們將stu的名字賦值為梁朝偉,此時(shí)CPU時(shí)間片耗盡了,另一個(gè)打印的線程搶到時(shí)間片的情況下 就會(huì)將原來(lái)的正確的值改為錯(cuò)誤的數(shù)據(jù) 從而產(chǎn)生并發(fā)錯(cuò)誤。
如何解決并發(fā)錯(cuò)誤
要想解決并發(fā)錯(cuò)誤加鎖是必須的
使用synchornized解決并發(fā)錯(cuò)誤
synchronize語(yǔ)法級(jí)別的加鎖 也叫? 互斥鎖=互斥標(biāo)記=鎖標(biāo)記=鎖旗標(biāo)=監(jiān)視器= Monitor
synchornized修飾代碼塊
synchronized(臨界資源){
//需要連續(xù)執(zhí)行的操作
}
synchornized修飾整個(gè)方法
public synchronized void add(){
}
//等價(jià)于
public void add(){
synchronized(){
}
}
注意:即便synchronized加在方法上,其實(shí)還是對(duì)對(duì)象進(jìn)行加鎖,而且鎖的是調(diào)用方法的那個(gè)對(duì)象Java世界里只有每個(gè)對(duì)象才有鎖標(biāo)記,所以加鎖只能對(duì)對(duì)象加鎖。
public class TestConcurrentError{
public static void main(String[] args){
Student stu = new Student("張朝偉","先生");
PrintThread pt = new PrintThread(stu);
ChangeThread ct = new ChangeThread(stu);
pt.start();
ct.start();
}
}
//1st.用于打印顯示數(shù)據(jù)的線程
class PrintThread extends Thread{
Student stu;
public PrintThread(Student stu){
this.stu = stu;
}
@Override
public void run(){
while(true){
synchronized(stu){//我們要對(duì)一組連續(xù)的操作加鎖 不要對(duì)所有操作加鎖
//我們?nèi)?只是鎖一次上廁所的過(guò)程 不要一輩子死在廁所里
System.out.println(stu);
}
}
}
}
class ChangeThread extends Thread{
Student stu;
public ChangeThread(Student stu){
this.stu = stu;
}
@Override
public void run(){
boolean isOkay = true;
while(true){
synchronized(stu){
if(isOkay){
stu.name = "張曼玉";
stu.gender = "女士";
}else{
stu.name = "梁朝偉";
stu.gender = "先生";
}
isOkay = !isOkay;
}
}
}
}
class Student{
String name;
String gender;
public Student(String name,String gender){
this.name = name;
this.gender = gender;
}
@Override
public String toString(){
return name + " : " + gender;
}
}
使用ReentrantLock解決并發(fā)錯(cuò)誤
java.util.concurrent.locks.ReentrantLock(jdk 5.0開(kāi)始):java包的工具包的并發(fā)包的 可重入鎖
ReentrantLock :lock(加鎖) unlock(解鎖):放在finally{}中
ReentrantLock可以在構(gòu)造方法中傳公平鎖和非公平鎖(公平與否針對(duì)第一個(gè)先來(lái)的線程而言)
公平鎖:new Reetrantlock(true);
- JDK6.0之前這個(gè)Lock的機(jī)制比synchronized效率高很多 JDK6.0開(kāi)始
- 重新對(duì)synchronized修改了底層實(shí)現(xiàn),加入了一堆新的概念 (偏向鎖 輕量級(jí)鎖 鎖的自旋機(jī)制) 從JDK6.0開(kāi)始 synchronized 跟 Lock性能上不相上下
import java.util.concurrent.locks.*;
public class TestConcurrentErrorWithLock{
public static void main(String[] args){
Lock lock = new ReentrantLock();
Student stu = new Student("張朝偉","先生");
PrintThread pt = new PrintThread(stu,lock);
ChangeThread ct = new ChangeThread(stu,lock);
pt.start();
ct.start();
}
}
//1st.用于打印顯示數(shù)據(jù)的線程
class PrintThread extends Thread{
Student stu;
Lock lock;
public PrintThread(Student stu,Lock lock){
this.stu = stu;
this.lock = lock;
}
@Override
public void run(){
while(true){
lock.lock();//鎖 既是一個(gè)名詞 又是一個(gè)動(dòng)詞
try{
//synchronized(stu){//我們要對(duì)一組連續(xù)的操作加鎖 不要對(duì)所有操作加鎖
//我們?nèi)?只是鎖一次上廁所的過(guò)程 不要一輩子死在廁所里
System.out.println(stu);
//}
}finally{
lock.unlock();
}
}
}
}
class ChangeThread extends Thread{
Student stu;
Lock lock;
public ChangeThread(Student stu,Lock lock){
this.stu = stu;
this.lock = lock;
}
@Override
public void run(){
boolean isOkay = true;
while(true){
//synchronized(stu){
lock.lock();
try{
if(isOkay){
stu.name = "張曼玉";
stu.gender = "女士";
}else{
stu.name = "梁朝偉";
stu.gender = "先生";
}
isOkay = !isOkay;
}finally{
lock.unlock();
}
//}
}
}
}
class Student{
String name;
String gender;//性別
public Student(String name,String gender){
this.name = name;
this.gender = gender;
}
@Override
public String toString(){
return name + " : " + gender;
}
}

此時(shí)已經(jīng)解決了并發(fā)錯(cuò)誤
到此這篇關(guān)于Java synchornized與ReentrantLock處理并發(fā)出現(xiàn)的錯(cuò)誤的文章就介紹到這了,更多相關(guān)Java synchornized與ReentrantLock內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java ReentrantLock條件鎖實(shí)現(xiàn)原理示例詳解
- 一文帶你掌握J(rèn)ava?ReentrantLock加解鎖原理
- 深入剖析Java ReentrantLock的源碼
- 圖解Java?ReentrantLock的條件變量Condition機(jī)制
- 詳解Java?ReentrantLock可重入,可打斷,鎖超時(shí)的實(shí)現(xiàn)原理
- java?ReentrantLock并發(fā)鎖使用詳解
- 圖解Java?ReentrantLock公平鎖和非公平鎖的實(shí)現(xiàn)
- java鎖機(jī)制ReentrantLock源碼實(shí)例分析
- Java?AQS中ReentrantLock條件鎖的使用
相關(guān)文章
SpringBoot整合Web開(kāi)發(fā)之文件上傳與@ControllerAdvice
@ControllerAdvice注解是Spring3.2中新增的注解,學(xué)名是Controller增強(qiáng)器,作用是給Controller控制器添加統(tǒng)一的操作或處理。對(duì)于@ControllerAdvice,我們比較熟知的用法是結(jié)合@ExceptionHandler用于全局異常的處理,但其作用不止于此2022-08-08
Nacos作為配置中心注冊(cè)監(jiān)聽(tīng)器方法
本文主要討論Nacos作為配置中心時(shí),其中配置內(nèi)容發(fā)生更改時(shí),我們的應(yīng)用程序能夠做的事。一般使用監(jiān)聽(tīng)器來(lái)實(shí)現(xiàn)這步操作,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2023-02-02
Java如何將Excel數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫(kù)
Java+mysql本地圖片上傳數(shù)據(jù)庫(kù)及下載示例
java實(shí)現(xiàn)簡(jiǎn)單學(xué)生管理系統(tǒng)項(xiàng)目

