java鎖學習(一)
阿新 • • 發佈:2019-05-14
作用
能夠保證同一時刻,最多隻有一個執行緒執行該段程式碼,以達到併發安全的效果
主要用於同時刻對執行緒間對任務進行鎖
地位
synchronized是JAVA的原生關鍵字,是JAVA中最基本的互斥手段,是併發程式設計中的元老角色
不使用併發的後果
不使用併發會導致多執行緒情況下,同一個資料被多個執行緒同時更改,造成結果和預期不一致導致蟲子的出生(bug)。
class MissRequestNumAsync implements Runnable { static public int i = 0; @Override public void run() { for (int j = 0; j < 100000; j ++) { i++; } } } public class SynchronizedObjectAction{ static MissRequestNumAsync m1 = new MissRequestNumAsync(); public static void main(String[] args) { System.out.println("消失的請求數-不使用併發的後果"); //消失的請求數 Thread t1 = new Thread(m1); Thread t2 = new Thread(m1); t1.start(); t2.start(); System.out.println(MissRequestNumAsync.i); } }
執行結果(並且每次都不一樣)
消失的請求數-不使用併發的後果
102171
鎖的分類
- 物件鎖(方法鎖、同步程式碼塊鎖)
- 類鎖(靜態鎖、class物件)
物件鎖
同步程式碼塊鎖
直接擼
//程式碼塊鎖 //劣勢:太多鎖會增加業務複雜度 //解決方式: 成熟的工具類 //除錯: thread.getStats(); class SyncObjArea implements Runnable{ static public int i = 0; Object sleepLock1 = new Object(); Object sleepLock2 = new Object(); @Override public void run() { //這裡有搶佔機制 synchronized (sleepLock1) { System.out.println("我是同步程式碼塊鎖1"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"執行結束"); } //這裡有搶佔機制 synchronized (sleepLock2) { System.out.println("我是同步程式碼塊鎖2"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"執行結束"); } } }
執行結果(多次執行,結果不一)
我是同步程式碼塊鎖1
Thread-2執行結束
我是同步程式碼塊鎖2
我是同步程式碼塊鎖1
Thread-3執行結束
Thread-2執行結束
我是同步程式碼塊鎖2
Thread-3執行結束
同步程式碼塊執行緒執行完畢
方法鎖
方法鎖預設是物件級別的(this)
//方法鎖 class SyncObjMethod implements Runnable { static public int i = 0; @Override public void run() { method(); } public synchronized void method(){ System.out.println("我是方法鎖"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"執行結束"); } }
執行結果
我是方法鎖
Thread-4執行結束
我是方法鎖
Thread-5執行結束
方法鎖形式 執行緒執行完畢
原始碼位置
明