Java多線程-同步:synchronized 和線程通信:生產者消費者模式

大傢伙週末愉快,小樂又來給大家獻上技術大餐。上次是說到了Java多線程的創建和狀態|樂字節,接下來,我們再來接着說Java多線程-同步:synchronized 和線程通信:生產者消費者模式。

一、同步:synchronized

多個線程同時訪問一個對象,可能造成非線程安全,數據可能錯誤,所謂同步:就是控制多個線程同時訪就是控制多線程操作同一個對象時,注意是同一個對象,數據的準確性, 確保數據安全,但是加入同步後因爲需要等待,所以效率相對低下。

如:一個蘋果,自己一個人去咬怎麼都不會出問題,但是多個人同時去咬,這個時候如果控制不好,就可能會咬到對方了。 再強調一下是一個蘋果。

12306 中的火車票,爲什麼搶到票時,需要等待,鎖定席位才付款?這就是確保一張票只能一個人去購買。

1、同步塊

synchronized +塊:同步塊

synchronized (引用類型|對象|類.class) {

}

2、同步方法

修飾符 synchronized 返回類型|void 方法簽名{

}

3、死鎖

過多的同步容易死鎖

/**
* 死鎖:容易造成死鎖
* @author Administrator
*
*/
public class TestDeadLock {
/**
* @param args
*/
public static void main(String[] args) {
Object obj1 =new Object();
Object obj2 =new Object();
new A(obj1,obj2).start();
new B(obj1,obj2).start();
} }
class A extends Thread{
Object obj1 ;
Object obj2;
public A() {
}
public A(Object obj1, Object obj2) {
super();
this.obj1 = obj1;
this.obj2 = obj2;
}
@Override
public void run() {
synchronized(obj1){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(obj2){
} 
}
System.out.println("給我煙");
} 
}
class B extends Thread{
Object obj1 ;
Object obj2;
public B() {
}
public B(Object obj1, Object obj2) {
super();
this.obj1 = obj1;
this.obj2 = obj2;
}
@Override
public void run() {
synchronized(obj2){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(obj1){
} }
System.out.println("給我錢");
} 
}

二、線程通信:生產者消費者模式

線程通信的目標是使線程間能夠互相發送信號。另一方面,線程通信使線程能夠等待其

他線程的信號。

Java 有一個內建的等待機制來允許線程在等待信號的時候變爲非運行狀態。

java.lang.Object 類定義了三個方法,wait()、notify()和 notifyAll()來實現這個等待機制。一個線程一旦調用了任意對象的 wait()方法,就會變爲非運行狀態,直到另一個線程調用了同一個對象的 notify()方法。爲了調用 wait()或者 notify(),線程必須先獲得那個對象的鎖。也就是說,線程必須在同步塊裏調用 wait()或者 notify()。

以下爲一個使用了 wait()和 notify()實現的線程間通信的共享對象:


 /**
* 街道
* @author Administrator
*
*/
public class Street {
//紅綠燈
//false 紅燈 -->人等 車走 -->換燈 通知人走
//true 綠燈 -->車等 人走 -->換燈 通知車走
private boolean flag=false;
//東西向 -->人道
public synchronized void west(){
if(flag==false){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
} 
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("東西向-->人走");
//換燈
this.flag =false;
this.notify(); //喚醒等待者
}
//南北向 車道
public synchronized void north(){
if(flag==true){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
} }
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("南北向-->車走");
//換燈
this.flag =true;
this.notify(); //喚醒等待者
}
 }
class Person extends Thread {
private Street s ;
public Person(Street s) {
this.s = s; }
public void run() {
for(int i=0;i<10;i++){
s.west(); //東西向
}
}
 }
class Car extends Thread {
private Street s ;
public Car(Street s) {
this.s = s; }
public void run() {
for(int i=0;i<10;i++){
s.north();
} 
} 
}

Java多線程的同步和線程通信就介紹到這裏,更多技術乾貨請關注樂字節。樂字節原創!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章