欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java?synchornized與ReentrantLock處理并發(fā)出現(xiàn)的錯(cuò)誤

 更新時(shí)間:2023年01月05日 08:45:31   作者:欲無(wú)緣  
synchronized機(jī)制提供了對(duì)每個(gè)對(duì)象相關(guān)的隱式監(jiān)視器鎖,并強(qiáng)制所有鎖的獲取和釋放都必須在同一個(gè)塊結(jié)構(gòu)中。當(dāng)獲取了多個(gè)鎖時(shí),必須以相反的順序釋放。即synchronized對(duì)于鎖的釋放是隱式的

什么是并發(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)有寫過(guò)將梁朝偉賦值為女士,也沒(méi)有寫過(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開始):java包的工具包的并發(fā)包的 可重入鎖

ReentrantLock :lock(加鎖) unlock(解鎖):放在finally{}中

ReentrantLock可以在構(gòu)造方法中傳公平鎖和非公平鎖(公平與否針對(duì)第一個(gè)先來(lái)的線程而言)

公平鎖:new Reetrantlock(true);

  • JDK6.0之前這個(gè)Lock的機(jī)制比synchronized效率高很多 JDK6.0開始
  • 重新對(duì)synchronized修改了底層實(shí)現(xiàn),加入了一堆新的概念 (偏向鎖 輕量級(jí)鎖 鎖的自旋機(jī)制) 從JDK6.0開始 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)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java如何將Excel數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫(kù)

    Java如何將Excel數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫(kù)

    這篇文章主要為大家詳細(xì)介紹了Java將Excel數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫(kù)的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Java之Spring整合Junit

    Java之Spring整合Junit

    Java Spring框架是一個(gè)輕量級(jí)的開源框架,具有很高的凝聚力和吸引力,本篇文章帶你了解如何配置數(shù)據(jù)源、注解開發(fā)以及整合Junit
    2023-04-04
  • Java+mysql本地圖片上傳數(shù)據(jù)庫(kù)及下載示例

    Java+mysql本地圖片上傳數(shù)據(jù)庫(kù)及下載示例

    本篇文章主要介紹了Java+mysql本地圖片上傳數(shù)據(jù)庫(kù)及下載示例,具有一定的參加價(jià)值,有興趣的可以了解一下。
    2017-01-01
  • Java 線程池全面總結(jié)與詳解

    Java 線程池全面總結(jié)與詳解

    在一個(gè)應(yīng)用程序中,我們需要多次使用線程,也就意味著,我們需要多次創(chuàng)建并銷毀線程。而創(chuàng)建并銷毀線程的過(guò)程勢(shì)必會(huì)消耗內(nèi)存。而在Java中,內(nèi)存資源是及其寶貴的,所以,我們就提出了線程池的概念
    2021-10-10
  • 深入理解final變量的初始化

    深入理解final變量的初始化

    本篇文章是對(duì)final變量的初始化進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • java實(shí)現(xiàn)簡(jiǎn)單學(xué)生管理系統(tǒng)項(xiàng)目

    java實(shí)現(xiàn)簡(jiǎn)單學(xué)生管理系統(tǒng)項(xiàng)目

    這篇文章主要介紹了java實(shí)現(xiàn)簡(jiǎn)單學(xué)生管理系統(tǒng)項(xiàng)目,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • 最新評(píng)論