1.synchronized與Lock的區別
(1)synchronized是java內置關鍵字,在jvm層面,Lock是個java類
(2)synchronized無法判斷是否獲取鎖的狀態,Lock可以判斷是否獲取到鎖
(3)synchronized會自動釋放鎖(a線程執行完同步代碼會釋放鎖,b線程執行過程中發生異常會釋放鎖),Lock需要在finally中手動釋放鎖(unlock()方法釋放鎖),否則容易造成線程死鎖
(4)用synchronized關鍵字的兩個線程1和線程2,如果當前線程1獲得鎖,線程2等待,如果線程1阻塞,線程2會一直等待下去;而Lock鎖就不一定會等待下去,如果嘗試獲取不到鎖,線程可以不用一直等待就結束了了
(5)synchronized的鎖可重入、不可中斷、非公平,而Lock鎖可重入、可判斷、可公平
(6)Lock鎖適合大量代碼的同步問題,synchronized鎖適合少量代碼的同步問題
package com.alisa.juc;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Tocket{ //資源類 = 實例變量 + 實例方法,線程操作資源類
private int number = 30;
Lock lock = new ReentrantLock();
public void sale(){
lock.lock();
try{
if(number > 0){
System.out.println(Thread.currentThread().getName() + "賣出第" + (number--) +"張票,還剩" + number +"張");
}
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
public class LockTest {
public static void main(String[] args) { //主線程,一切程序的入口
Tocket tocket = new Tocket();
//使用匿名內部類
/*new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i<40; i++){
tocket.sale();
}
}
}, "A").start();
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i<40; i++){
tocket.sale();
}
}
}, "B").start();
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i<40; i++){
tocket.sale();
}
}
}, "C").start();*/
//使用Lambda表達式
new Thread(() -> {
for (int i = 0; i < 40; i++) {
tocket.sale();
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 40; i++) {
tocket.sale();
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 40; i++) {
tocket.sale();
}
}, "C").start();
}
}