1. 程式人生 > 實用技巧 >java 多執行緒安全--- synchronized 關鍵字

java 多執行緒安全--- synchronized 關鍵字

1.什麼執行緒安全問題?

1.1 就是當多個執行緒共享同一個全域性變數,同時對這個變數做寫的時間,可能會受到其他執行緒的干擾,導致資料有誤。


class ThreadDemos implements Runnable {
private int movie = 8;

@Override
public void run() {
while (movie > 0) {
try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
sell();
}
}

public void sell() {
if (movie > 0) {
System.out.println(Thread.currentThread().getName() + ",出售第" + (8 - movie + 1) + "票");
movie--;

}


}
}

public class ThreadDemo {

public static void main(String[] args) {
ThreadDemos threadDemos = new ThreadDemos();
Thread t1 = new Thread(threadDemos, "美團買票");
Thread t2 = new Thread(threadDemos, "門店買票");
t1.start();
t2.start();
}

}

執行結果:

由此我們可以發現2個視窗會出現同一張票,就出現了執行緒安全問題,如果2個不同的人買了同一張票,這個時間檢票員是該讓哪個人進去看電影那?

2.怎麼樣解決執行緒安全問題?

2.1 使用synchronized 同步程式碼塊 程式碼如下:


class ThreadDemos implements Runnable {
private int movie = 8;
private Object object = new Object();

@Override
public void run() {
while (movie > 0) {
try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
sell();
}
}

public void sell() {
synchronized (object) {
if (movie > 0) {
System.out.println(Thread.currentThread().getName() + ",出售第" + (8 - movie + 1) + "票");
movie--;

}
}


}
}

public class ThreadDemo {

public static void main(String[] args) {
ThreadDemos threadDemos = new ThreadDemos();
Thread t1 = new Thread(threadDemos, "美團買票");
Thread t2 = new Thread(threadDemos, "門店買票");
t1.start();
t2.start();
}

}
程式碼執行結果:

使用 synchronized同步程式碼塊 就不會出現2個視窗會出現同一張票的安全性問題

使用synchronized的 條件:1.必須要有2個執行緒以上的,需要同步 2.多個執行緒想要同步,必須要使用同一把鎖 3.保證只有一個執行緒執行執行

使用synchronized同步程式碼塊 的原理:有一個執行緒已經拿到鎖了,其他執行緒已經有cpu執行的,那麼這個執行緒會等待拿到鎖的那個執行緒執行完畢釋放鎖

使用synchronized的缺點:效率低,因為執行緒會搶鎖

2.2使用 同步函式解決執行緒安全:


class ThreadDemos implements Runnable {
private int movie = 8;

@Override
public void run() {
while (movie > 0) {
try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
sell();
}
}

public synchronized void sell() {
if (movie > 0) {
System.out.println(Thread.currentThread().getName() + ",出售第" + (8 - movie + 1) + "票");
movie--;

}


}
}

public class ThreadDemo05 {

public static void main(String[] args) {
ThreadDemos threadDemos = new ThreadDemos();
Thread t1 = new Thread(threadDemos, "美團買票");
Thread t2 = new Thread(threadDemos, "門店買票");
t1.start();
t2.start();
}

}
程式碼執行結果:

使用同步函式 在需要同步的方法上面加上synchronized 關鍵字,同步函式使用的是 this 鎖

2.3使用靜態同步函式

class ThreadDemos implements Runnable {
private static int movie = 8;

@Override
public void run() {
while (movie > 0) {
try {
Thread.sleep(10);
} catch (Exception e) {
// TODO: handle exception
}
sell();
}
}

public static synchronized void sell() {

if (movie > 0) {
System.out.println(Thread.currentThread().getName() + ",出售第" + (8 - movie + 1) + "票");
movie--;

}


}
}

public class ThreadDemo05 {

public static void main(String[] args) {
ThreadDemos threadDemos = new ThreadDemos();
Thread t1 = new Thread(threadDemos, "美團買票");
Thread t2 = new Thread(threadDemos, "門店買票");
t1.start();
t2.start();
}

}
執行結果:

靜態同步函式使用的是 當前位元組碼檔案