1、JUC
java.util.concurrent在并發(fā)編程中使用的工具類(lèi)

2、Lock
Lock是java.util.concurrent.locks下的接口

3、Lock跟Synchronized區(qū)別
- synchronized是java內(nèi)置關(guān)鍵詞,在jvm層面;Lock是個(gè)java接口
- synchronized無(wú)法判斷是否獲取鎖的狀態(tài),Lock可以判斷是否獲取到鎖
- synchronized會(huì)自動(dòng)釋放鎖(a線程執(zhí)行完同步代碼塊會(huì)釋放鎖,b線程執(zhí)行過(guò)程中發(fā)生異常會(huì)釋放鎖);Lock需要在finally中手工釋放鎖(unlock()方法釋放鎖),否則容易造成死鎖
- 用synchronized關(guān)鍵字的兩個(gè)線程1和線程2,如果當(dāng)前線程1獲得鎖,線程2線程等待。如果線程1阻塞,線程2則會(huì)一直等待下去,而Lock鎖就不一定會(huì)等待下去,如果嘗試獲取不到鎖,線程可以不用一直等待就結(jié)束了;
- synchronized的鎖可重入、不可中斷、非公平,而Lock鎖可重入、可判斷、可公平(兩者皆可)
- Lock鎖適合大量同步的代碼的同步問(wèn)題,synchronized鎖適合代碼少量的同步問(wèn)題
4、Lock使用

class X {
//Lock是接口,ReentrantLock()是其中一個(gè)實(shí)現(xiàn)
//private Lock lock = new ReentrantLock();
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}
5、售賣(mài)電影票例子
/**
* 資源類(lèi)
*/
class Ticket{
private int count = 20;
private Lock lock = new ReentrantLock();
public void sale(){
//上鎖
lock.lock();
try {
if (count > 0){
count--;
System.out.println(Thread.currentThread().getName()+"正在買(mǎi)票,還是剩下" + count);
}
}catch (Exception e){
e.printStackTrace();
}finally {
//手動(dòng)釋放鎖
lock.unlock();
}
}
}
public class LockTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(()->{
for (int i = 0; i < 20; i++) {
ticket.sale();
}
},"AA").start();
new Thread(()->{
for (int i = 0; i < 20; i++) {
ticket.sale();
}
},"BB").start();
new Thread(()->{
for (int i = 0; i < 20; i++) {
ticket.sale();
}
},"CC").start();
}
}