java鎖學習(二)
阿新 • • 發佈:2019-05-15
類鎖
類鎖 !!!! java類有很多物件 ,但是隻有一個class物件 !!!!
所以,類鎖,就是針對當前類的Class物件的鎖
類鎖同一時刻只能被一個物件獲取
- synchronized放在static方法上(靜態鎖)
- synchronized放在class物件上
靜態鎖
class SyncClassStatic implements Runnable { @Override public void run() { method(); } public static synchronized void method() { System.out.println("我是類鎖中靜態鎖"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"執行結束"); } } result: 我是類鎖中靜態鎖 Thread-6執行結束 我是類鎖中靜態鎖 Thread-7執行結束 類鎖,靜態鎖執行完畢
class物件鎖
class SyncClassObj implements Runnable{ @Override public void run() { method(); } private void method(){ synchronized (SyncClassObj.class) { System.out.println("我是類鎖中class物件鎖"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"執行結束"); } } } result: 我是類鎖中class物件鎖 Thread-8執行結束 我是類鎖中class物件鎖 Thread-9執行結束 類鎖,class物件執行完畢
常見場景和問題
-
兩個執行緒同時訪問一個物件的同步方法會怎樣?
依次執行(鎖住的是同一個物件)
-
兩個執行緒訪問的是兩個物件的同步方法又會怎樣?
隨機執行(鎖住的是不同的物件)
-
兩個執行緒訪問的是synchronized的靜態方法會怎樣?
依次執行(鎖住的是同一個類)
-
同時訪問同步方法與非同步方法會怎樣?
只鎖加了synchronized的方法,其他方法不會收到影響
class SyncObjLock implements Runnable { @Override public void run() { if(Thread.currentThread().getName().equals("Thread-0")) { syncMethod(); }else{ asyncMethod(); } } private synchronized void syncMethod() { System.out.println("我被鎖了"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"執行結束"); } private void asyncMethod() { System.out.println("我沒被鎖"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"執行結束"); } } 同時開始,同時結束: 我被鎖了 我沒被鎖 Thread-0執行結束 Thread-1執行結束
- 訪問同一個物件的不同的普通同步方法會怎樣?
class SyncDiff implements Runnable{
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")) {
syncMethod1();
}else{
syncMethod2();
}
}
private synchronized void syncMethod1()
{
System.out.println("我被鎖了,我是方法1");
try{
Thread.sleep(3000);
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"執行結束");
}
private synchronized void syncMethod2()
{
System.out.println("我被鎖了,我是方法2");
try{
Thread.sleep(3000);
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"執行結束");
}
}
同時開始,同時結束:
我被鎖了
我沒被鎖
Thread-0執行結束
Thread-1執行結束
- 同時訪問靜態sync和非靜態sync方法
class SyncStaticOrNo implements Runnable {
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")) {
syncMethod1();
}else{
syncMethod2();
}
}
private synchronized void syncMethod1()
{
System.out.println("我被物件鎖");
try{
Thread.sleep(3000);
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"執行結束");
}
private static synchronized void syncMethod2()
{
System.out.println("我是類鎖");
try{
Thread.sleep(3000);
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"執行結束");
}
}
同時開始,同時結束:
我被鎖了
我沒被鎖
Thread-0執行結束
Thread-1執行結束
- 方法丟擲異常後,會釋放鎖嗎?
會,jvm幫我們釋放了
class SyncExc implements Runnable{
@Override
public void run() {
method1();
}
private synchronized void method1()
{
System.out.println(Thread.currentThread().getName()+"開始");
try{
Thread.sleep(3000);
}catch (Exception e) {
e.printStackTrace();
}
throw new RuntimeException("");
// System.out.println("執行結束");
}
}
Thread-0開始
Exception in thread "Thread-0" java.lang.RuntimeException:
at Thread.SyncExc.method1(SynchronizedObject.java:187)
at Thread.SyncExc.run(SynchronizedObject.java:176)
at java.lang.Thread.run(Thread.java:748)
Thread-1開始
Exception in thread "Thread-1" java.lang.RuntimeException:
at Thread.SyncExc.method1(SynchronizedObject.java:187)
at Thread.SyncExc.run(SynchronizedObject.java:176)
at java.lang.Thread.run(Thread.java:748)
鎖的使用場景及分析
整個系統全域性同步用類鎖,區域性鎖用物件鎖
對比下,就像一樣,鎖的範圍越大,效能自然越低(粒度:類鎖>物件鎖 效能