------- 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>