Java基礎04——多線程

------- android培訓java培訓、期待與您交流! ----------

線程安全問題產生的原因:

1,多個線程在操作共享的數據。

2,操作共享數據的線程代碼有多條。

當一個線程在執行操作共享數據的多條代碼過程中,其他線程參與了運算。

就會導致線程安全問題的產生。

解決思路; 就是將多條操作共享數據的線程代碼封裝起來,當有線程在執行這些代碼的時候,其他線程時不可以參與運算的。 必須要當前線程把這些代碼都執行完畢後,其他線程纔可以參與運算。在java中,用同步代碼塊就可以解決這個問題。

同步代碼塊的格式:

synchronized(obj)

{
需要被同步的代碼
}
對象如同鎖,持有鎖的線程可以在同步中執行,否則,即使獲取cpu的執行權,也不能進去
同步的前提:

1. 必須有>=2個以上的線程

2. 必須是多個線程使用同一個鎖
好處: 解決了多線程的安全問題

弊端: 多個線程需要判斷,較爲消耗資源。

同步函數使用的鎖是 this:同步函數需要被對象調用,函數都有一個所屬對象引用,就是this

驗證如下:2個線程買票,一個線程在同步代碼塊,一個在同步函數。


<span style="font-size:12px;">class Ticket implements Runnable {
	private int tick = 300;
	Object obj = new Object();
	boolean flag = true;

	public void run() {
		if (flag) {
			while (true) {
				synchronized (this) {
					if (tick > 0) {
						try {
							Thread.sleep(10);
						} catch (Exception e) {
						}
						System.out.println(Thread.currentThread().getName()
								+ "...codeblock..." + tick--);
					}
				}
			}
		} else
			while (true)
				show();
	}

	public synchronized void show() {
		if (tick > 0) {
			try {
				Thread.sleep(10);
			} catch (Exception e) {
			}
			System.out.println(Thread.currentThread().getName()
					+ "...codeblock..." + tick--);

		}
	}
}

public class TicketLockDemo {

	public static void main(String[] args)
	{
		Ticket t = new Ticket();
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		t1.start();
		try{Thread.sleep(10);} catch(Exception e){}
		t.flag = false;
		t2.start();
	}
}</span>

單例設計模式之懶漢式:

<span style="font-size:12px;">class Single 
{
	public static final Single s = new Single();
	private Single(){};
	public static Single getInstance()
	{
		return s;
	}
}</span>
單例設計模式之餓漢式(多線程):

區別:延遲加載

造成問題:如果多線程訪問時或有安全問題

解決辦法:可以加同步來解決(同步的鎖是該類所屬的字節碼對象),同步代碼塊或同步函數都能解決,但有些低效,用雙重判斷的方法可以解決(減少判斷的次數)

<span style="font-size:12px;">class Single 
{
	public static Single s = null;
	private Single(){};
	public static Single getInstance()
	{
		if(s==null)
		{
			synchronized (Single.class) //靜態方法的鎖是.class
			{
				if(s==null)</span>
<span style="font-size:12px;"><span style="white-space:pre">					</span>//---->A
					s = new Single();
			}
		}
		return s;
	}
} //分析:A線程通過第一個if語句,獲得鎖,通過第二個if語句,掛載;這時B線程通過第一個if語句,獲取不到鎖,不能繼續執行;A線程繼續執行,s!=null,這時其他線程不可能通過第一個if語句,不會向下執行。</span>
死鎖:同步中嵌套同步。
<span style="font-size:12px;">class Test implements Runnable
{
	private boolean flag;
	Test(boolean flag)
	{
		this.flag = flag;
	}
	public void run()
	{
		if(flag)
		{
			synchronized (MyLock.locka) 
			{
				System.out.println("if locka");
				synchronized (MyLock.lockb)
				{
					System.out.println("if lockb");
				}
			}
		}
		else
		{
			synchronized (MyLock.lockb) 
			{
				System.out.println("else lockb");
				synchronized (MyLock.locka)
				{
					System.out.println("else locka");
				}
			}
		}	
	}
}

class MyLock
{
	static Object locka = new Object();
	static Object lockb = new Object();
}
public class DeadLockTest {

	public static void main(String[] args)
	{
		Thread t1 = new Thread(new Test(true));
		Thread t2 = new Thread(new Test(false));
		t1.start();
		t2.start();
	}
}</span>


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