線程同步
并發:同一個對象被多個線程同時操作
同步方法
-
方法里面需要修改的內容才需要鎖
package com.Spp.syn;
?
同步塊:
-
synchronized(Obj){}
-
Obj稱之為同步監視器
-
同步監視器的執行過程
-
第一個線程訪問,鎖定同步監視器,執行其中代碼
-
第二個線程訪問,發現同步監視器被鎖定,無法訪問
-
第一個線程訪問完畢,解鎖同步監視器
-
第二個線程訪問,發現同步監視器沒有鎖,然后鎖定并訪問
package com.Spp.syn;
?
public class UnSafeBank {
public static void main(String[] args) {
Account account = new Account(3600,"備用金");
Drawing dra1 = new Drawing(account,280,"dra1");
Drawing dra2 = new Drawing(account,100,"dra2");
dra1.start();
dra2.start();
}
}
?
死鎖
執行卡死
package com.kuang.ThreadLesson;
?
public class DeadLock {
public static void main(String[] args) {
MakeUp g1 = new MakeUp(0,"11");
MakeUp g2 = new MakeUp(1,"22");
g1.start();
g2.start();
}
}
順利執行
private void makeup() throws InterruptedException {
if(choice == 0){
synchronized (lipStick){
System.out.println(this.name+"獲得口紅的鎖");
Thread.sleep(100);
}
synchronized (mirror){
System.out.println(this.name+"獲得鏡子的鎖");
}
}else{
synchronized (mirror){
System.out.println(this.name+"獲得鏡子的鎖");
Thread.sleep(200);
}
synchronized (lipStick){
System.out.println(this.name+"獲得口紅的鎖");
}
}
}
Lock(鎖)
ReentrantLock:可重入鎖
ReentrantLock類實現Lock鎖
package com.kuang.ThreadLesson;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
new Thread(buyTicket).start();
new Thread(buyTicket).start();
new Thread(buyTicket).start();
}
}
?
class BuyTicket implements Runnable{
int ticketNumbers = 10;
synchronized 與Lock的對比
-
Lock是顯示鎖(手動開啟和關閉),synchronized是隱式鎖,出了作用域自動釋放
-
Lock只有代碼塊鎖,synchronized有代碼塊鎖和方法鎖
-
使用Lock鎖,JVM將花費較少的時間來調度線程,性能更好。并且具有更好的擴展性(提供更多的子類)
-
優先使用順序:Lock > 同步代碼塊 > 同步方法