甘孜州住房和城鄉(xiāng)規(guī)劃建設局網(wǎng)站外包公司為什么沒人去
Synchronized
稱之為”同步鎖
作用:
????????保證在同一時刻, 被修飾的代碼塊或方法只會有一個線程執(zhí)行,以達到保證并發(fā)安全的效果
用法:
??????? 1.修飾方法:方法鎖,鎖的對象是當前對象
??????? 2.修飾靜態(tài)方法:類鎖,鎖的對象是當前的類,實際是這個類的.class對象
??????? 3.修飾代碼塊:對象鎖,鎖的對象是synchronized修飾的對象
案例:
public class TestThread {public static void main(String[] arge){Ticket ticket = new Ticket();new Thread(()->{for(int i=1;i<40;i++){ticket.ticket();}},"A").start();new Thread(()->{for(int i=1;i<40;i++){ticket.ticket();}},"B").start();new Thread(()->{for(int i=1;i<40;i++){ticket.ticket();}},"C").start();}
}class Ticket{private int num = 20;synchronized void ticket(){if(num > 0){System.out.println(Thread.currentThread().getName()+"剩余票數(shù):"+num--);}}
}
修飾方法:
public synchronized void method()
{
}
修飾代碼塊:
class SyncThread implements Runnable {private static int count;public SyncThread() {count = 0;}public void run() {synchronized(this) {for (int i = 0; i < 5; i++) {try {System.out.println(Thread.currentThread().getName() + ":" + (count++));Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}}public int getCount() {return count;}
}public class Demo00 {public static void main(String args[]){ SyncThread s = new SyncThread();Thread t1 = new Thread(s);Thread t2 = new Thread(s);t1.start();t2.start();}
}
? 修飾類:
????????給class加鎖和上例的給靜態(tài)方法加鎖是一樣的,所有對象公用一把鎖
class ClassName {public void method() {synchronized(ClassName.class) {}}
}
注意:
??????? 1.在定義接口方法時不能使用synchronized關鍵字;構造方法不能使用synchronized關鍵字
??????? 2.實現(xiàn)同步是要很大的系統(tǒng)開銷作為代價的,甚至可能造成死鎖,所以盡量避免無謂的同步控制
??????? 3.每個對象只有一個鎖與之相關聯(lián),誰拿到這個鎖誰就可以運行它所控制的那段代碼
Lock
Lock是一個同步線程機制;
主要方法:
????????lock():獲取鎖,加鎖
????????tryLock():判斷鎖是否可用
????????unlock():釋放鎖
使用:
public class TestThread2 {public static void main(String[] arge){Ticket2 ticket = new Ticket2();new Thread(()->{for(int i=1;i<40;i++){ticket.ticket();}},"A").start();new Thread(()->{for(int i=1;i<40;i++){ticket.ticket();}},"B").start();new Thread(()->{for(int i=1;i<40;i++){ticket.ticket();}},"C").start();}
}class Ticket2{private int num = 20;void ticket(){Lock lock = new ReentrantLock();lock.lock();try{if(num > 0){System.out.println(Thread.currentThread().getName()+"剩余票數(shù):"+num--);}}catch (Exception e){e.printStackTrace();}finally {lock.unlock();}}
}
ReentrantLock
????????重入鎖也叫做遞歸鎖,指的是同一線程 外層函數(shù)獲得鎖之后 ,內(nèi)層遞歸函數(shù)仍然有獲取該鎖的代碼,但不受影響。避免死鎖問題
public class ReentrantDemo implements Runnable {Lock lock = new ReentrantLock();@Overridepublic void run() {set();}public void set() {try {lock.lock();System.out.println("set 方法");get();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();// 必須在finally中釋放}}public void get() {try {lock.lock();System.out.println("get 方法");} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public static void main(String[] args) {ReentrantDemo reentrantDemo = new ReentrantDemo();new Thread(reentrantDemo).start();}
}
????????同一個線程,首先在set方法中獲取鎖,然后調用get方法,get方法中重復獲取同一個鎖。兩個方法都執(zhí)行成功
ReentrantReadWriteLock
讀寫鎖,可以分別獲取讀鎖或寫鎖。
特點:
????????讀鎖使用共享模式;寫鎖使用獨占模式;讀鎖可以在沒有寫鎖的時候被多個線程同時持有,寫鎖是獨占的。當有讀鎖時,寫鎖就不能獲得;而當有寫鎖時,除了獲得寫鎖的這個線程可以獲得讀鎖外,其他線程不能獲得讀鎖
常用方法:
??????? writeLock():獲取寫鎖
??????? readLock():獲取讀鎖
區(qū)別:
??????? 1.synchronized內(nèi)置關鍵字;lock是一個Java類
??????? 2.synchronized無法判斷鎖狀態(tài);lock可以判斷是否獲取到鎖
??????? 3.synchronized會自動釋放鎖;lock必須手動釋放鎖,不釋放會造成死鎖
??????? 4.synchronized可重入鎖,不可以中斷,非公平;lock可重入鎖,可以判斷鎖,非公平(可以設置)
??????? 5.synchronized適合鎖少量的代碼同步問題;lock適合鎖大量的同步代碼