為什麼要用鎖(Lock)? 鎖 相對於 synchronized 機制,是更加靈活的,它一樣能夠解決執行緒不安全的問題;
java.util.concurrent.locks.ReentrantLock;
是JDK 5.0新增的特性,新特性可以考慮優先使用/**
* 演示使用Lock解決執行緒不安全問題
* @author sunwc
* @create 2023-03-24 上午 11:18
*/
public class LockTest {
public static void main(String[] args) {
Window window = new Window();
Thread t1 = new Thread(window);
t1.setName("窗口1");
Thread t2 = new Thread(window);
t2.setName("窗口2");
Thread t3 = new Thread(window);
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
/**
* 窗口類
*/
class Window implements Runnable {
private int ticketAmount = 20;
@Override
public void run() {
while (ticketAmount > 0) {
if (ticketAmount > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +" : 售出的票號 - "+ ticketAmount);
ticketAmount--;
}
}
}
}
演示執行緒不安全輸出結果:
窗口3 : 售出的票號 - 20
窗口1 : 售出的票號 - 20
窗口2 : 售出的票號 - 20
窗口1 : 售出的票號 - 17
窗口3 : 售出的票號 - 17
窗口2 : 售出的票號 - 17
窗口3 : 售出的票號 - 14
窗口2 : 售出的票號 - 14
窗口1 : 售出的票號 - 14
窗口2 : 售出的票號 - 11
窗口1 : 售出的票號 - 11
窗口3 : 售出的票號 - 11
窗口2 : 售出的票號 - 8
窗口1 : 售出的票號 - 8
窗口3 : 售出的票號 - 8
窗口3 : 售出的票號 - 5
窗口1 : 售出的票號 - 5
窗口2 : 售出的票號 - 5
窗口1 : 售出的票號 - 2
窗口3 : 售出的票號 - 2
窗口2 : 售出的票號 - 2
窗口1 : 售出的票號 - -1
修改窗口類
class Window implements Runnable {
private int ticketAmount = 20;
// 1.創建Lock物件
// new ReentrantLock(boolean fair) fair默認false;若設置true,執行緒先進來先執行(先進先出)
ReentrantLock reentrantLock = new ReentrantLock(true);
@Override
public void run() {
while (ticketAmount > 0) {
try {
// 2. 手動取得同步鎖
reentrantLock.lock();
if (ticketAmount > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +" : 售出的票號 - "+ ticketAmount);
ticketAmount--;
}
} finally {
// 3.手動釋放同步鎖
reentrantLock.unlock();
}
}
}
}
解決執行緒不安全輸出結果:
窗口1 : 售出的票號 - 20
窗口2 : 售出的票號 - 19
窗口3 : 售出的票號 - 18
窗口1 : 售出的票號 - 17
窗口2 : 售出的票號 - 16
窗口3 : 售出的票號 - 15
窗口1 : 售出的票號 - 14
窗口2 : 售出的票號 - 13
窗口3 : 售出的票號 - 12
窗口1 : 售出的票號 - 11
窗口2 : 售出的票號 - 10
窗口3 : 售出的票號 - 9
窗口1 : 售出的票號 - 8
窗口2 : 售出的票號 - 7
窗口3 : 售出的票號 - 6
窗口1 : 售出的票號 - 5
窗口2 : 售出的票號 - 4
窗口3 : 售出的票號 - 3
窗口1 : 售出的票號 - 2
窗口2 : 售出的票號 - 1
本文介紹了如何使用鎖 將部分程式邏輯達到同步的效果,Lock的使用實際上會更靈活,因為它比較偏向人為去控制,哪時候開執行同步、哪時候結束同步,達到立竿見影的效果
基礎鞏固:有關透過實現類 implements interface Runnable 達成 Multi-threading,可以參考我的另一篇文章 Java - Thread 執行緒(二) - interface Runnable