用於解決多執行緒安全問題的三種方式
阿新 • • 發佈:2019-01-09
用於解決多執行緒安全問題的方式:
1. 同步程式碼塊 (隱式鎖)
2. 同步方法(隱式鎖)
3. 同步鎖 Lock( jdk 1.5 後)
注意:是一個顯示鎖,需要通過 lock() 方法上鎖,必須通過 unlock() 方法進行釋放鎖
下面舉一個售票例子:
1)同步程式碼塊
package com.lxj.juc; public class TestSync { public static void main(String[] args) { Ticket ticket = new Ticket(); new Thread(ticket).start(); new Thread(ticket).start(); new Thread(ticket).start(); } } class Ticket implements Runnable{ private int ticket = 100; @Override public void run() { while(true) { synchronized(this) { //this代表對當前物件上鎖 if(ticket > 0) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" : 購票成功,餘票為:" + --ticket ); }else { break; } } } } }
執行結果:
Thread-0 : 購票成功,餘票為:99
Thread-0 : 購票成功,餘票為:98
Thread-2 : 購票成功,餘票為:97
.....
Thread-2 : 購票成功,餘票為:7
Thread-0 : 購票成功,餘票為:6
Thread-0 : 購票成功,餘票為:5
Thread-1 : 購票成功,餘票為:4
Thread-1 : 購票成功,餘票為:3
Thread-0 : 購票成功,餘票為:2
Thread-0 : 購票成功,餘票為:1
Thread-2 : 購票成功,餘票為:0
2)同步方法
package com.lxj.juc; public class TestSync { public static void main(String[] args) { Ticket ticket = new Ticket(); new Thread(ticket).start(); new Thread(ticket).start(); new Thread(ticket).start(); } } class Ticket implements Runnable { private int ticket = 100; @Override public void run() { while (true) { if (ticket > 0) { int i = purchase(); if(i == 0) { break; } }else { break; } } } private synchronized int purchase() { if (ticket > 0) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " : 購票成功,餘票為:" + --ticket); }else { return 0; } return 1; } }
執行結果: Thread-0 : 購票成功,餘票為:99 Thread-0 : 購票成功,餘票為:98 Thread-0 : 購票成功,餘票為:97 Thread-2 : 購票成功,餘票為:96 Thread-1 : 購票成功,餘票為:95 .... Thread-1 : 購票成功,餘票為:8 Thread-2 : 購票成功,餘票為:7 Thread-2 : 購票成功,餘票為:6 Thread-0 : 購票成功,餘票為:5 Thread-0 : 購票成功,餘票為:4 Thread-0 : 購票成功,餘票為:3 Thread-2 : 購票成功,餘票為:2 Thread-1 : 購票成功,餘票為:1 Thread-2 : 購票成功,餘票為:0
3)同步鎖lock
package com.lxj.juc;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestSync {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(ticket).start();
new Thread(ticket).start();
new Thread(ticket).start();
}
}
class Ticket implements Runnable {
private int ticket = 100;
private Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
lock.lock(); //上鎖
try {
if (ticket > 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " : 購票成功,餘票為:" + --ticket);
}else {
break;
}
} finally {
lock.unlock(); //解鎖
}
}
}
}
執行結果:
Thread-0 : 購票成功,餘票為:99
Thread-1 : 購票成功,餘票為:98
Thread-1 : 購票成功,餘票為:97
Thread-1 : 購票成功,餘票為:96
Thread-1 : 購票成功,餘票為:95
Thread-2 : 購票成功,餘票為:94
......
Thread-0 : 購票成功,餘票為:6
Thread-0 : 購票成功,餘票為:5
Thread-1 : 購票成功,餘票為:4
Thread-2 : 購票成功,餘票為:3
Thread-2 : 購票成功,餘票為:2
Thread-2 : 購票成功,餘票為:1
Thread-2 : 購票成功,餘票為:0