天天看點

多線程安全問題----同步代碼塊

多線程安全問題

1.1解決線程安全問題的基本思想

(1)原因:當程式的多條語句在操作線程共享資料時(如買票例子中的票就是共享資源),

由于線程的随機性導緻,一個線程對多條語句,執行了一部分還沒執行完,另一個線程搶奪

到cpu 執行權參與進來執行,此時就導緻共享資料發生錯誤。比如買票例子中列印重票和

錯票的情況。

(2)解決方法:對多條操作共享資料的語句進行同步

首先想為什麼出現問題?(也是我們判斷是否有問題的标準)

  是否是多線程環境

  是否有共享資料

  是否有多條語句操作共享資料

如何解決多線程安全問題呢?

基本思想:讓程式沒有安全問題的環境。

怎麼實作呢?

把多個語句操作共享資料的代碼給鎖起來,讓任意時刻隻能有一個線程執行即可。

.2Java 中多線程同步是什麼?

同步是用來解決多線程的安全問題的,在多線程中,同步能控制對共享資料的通路。

如果沒有同步,當一個線程在修改一個共享資料時,而另外一個線程正在使用或者更新同一

個共享資料,這樣容易導緻程式出現錯誤的結果。

1.3什麼是鎖?鎖的作用是什麼?

鎖就是對象, 鎖的作用是保證線程同步,解決線程安全問題。

持有鎖的線程可以在同步中執行,沒有鎖的線程即使獲得cpu 執行權,也進不去。

1.4同步的前提

(1)必須保證有兩個以上線程

(2)必須是多個線程使用同一個鎖,即多條語句在操作線程共享資料

(3)必須保證同步中隻有一個線程在運作

1.5. 同步的好處和弊端

好處:同步解決了多線程的安全問題

弊端:多線程都需要判斷鎖,比較消耗資源

1.6解決線程安全問題實作1

(1)同步代碼塊:

可以指定需要擷取哪個對象的同步鎖,使用synchronized 的代碼塊同樣需要鎖,但

他的鎖可以是任意對象,考慮到安全問題,一般還是使用同一個對象,相對來說效率較高。

注意:

雖然同步代碼快的鎖可以使任何對象,但是在進行多線程通信使用同步代碼快時,

必須保證同步代碼快的鎖的對象和,否則會報錯。

同步方法的鎖是this,也要保證同步方法的鎖的對象和調用wait、notify 和

notifyAll 的對象是同一個對象,也就是都是this 鎖代表的對象。

格式:

synchronized(對象){需要同步的代碼;}

同步可以解決安全問題的根本原因就在那個對象上。該對象如同鎖的功能。

同步代碼塊的對象可以是哪些呢?

下面就電影院買票問題進行說明:

package java.thread;

/**
 * 線程同步
 */
public class ThreadDemo4 {
	public static void main(String[] args) {
		Saler s1 = new Saler("s1",1);
		Saler s2 = new Saler("s2",1);
		s1.start();
		s2.start();
	}
}

/**
 * 售票員
 */
class Saler extends Thread {
	//總票數
	private static int tickets = 100 ;

	private String name0;

	private int sleep;

	public Saler(String name0, int sleep) {
		this.name0 = name0;
		this.sleep = sleep;
	}

	public String getName0() {
		return name0;
	}

	public void setName0(String name0) {
		this.name0 = name0;
	}

	public void run() {
		try {
			while(true){
				int temp = 0 ;
				synchronized (Saler.class){
					temp = tickets ;
					Thread.sleep(50);
					tickets -- ;
				}
				if(temp <= 0 ){
					return ;
				}
				else{
					System.out.println(name0 +" : " + temp);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
           

繼續閱讀