java 多執行緒安全--- synchronized 關鍵字
阿新 • • 發佈:2020-07-23
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();
}
}
執行結果:
靜態同步函式使用的是 當前位元組碼檔案