同步方法鎖住整個方法,粒度較粗。同步代碼塊(synchronized(obj) { ... })允許僅鎖住訪問共享資源的關鍵區段,減少鎖持有時間,提升並發性能。
/**
* Java線程:線程的同步-同步代碼塊
* @author leizhimin
*/
public class Test {
public static void main(String[] args) {
User u = new User("張三", 100);
MyThread t1 = new MyThread("線程A", u, 20);
MyThread t2 = new MyThread("線程B", u, -60);
MyThread t3 = new MyThread("線程C", u, -80);
MyThread t4 = new MyThread("線程D", u, -30);
MyThread t5 = new MyThread("線程E", u, 32);
MyThread t6 = new MyThread("線程F", u, 21);
t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); t6.start();
}
}
class MyThread extends Thread {
private User u; private int y;
MyThread(String name, User u, int y) { super(name); this.u = u; this.y = y; }
public void run() { u.oper(y); }
}
class User {
private String code; private int cash;
User(String code, int cash) { this.code = code; this.cash = cash; }
public String getCode() { return code; }
public void setCode(String code) { this.code = code; }
/** 業務方法:使用同步代碼塊 */
public void oper(int x) {
try {
Thread.sleep(10L);
synchronized (this) { // 僅鎖住關鍵修改區
this.cash += x;
System.out.println(Thread.currentThread().getName() + "運行結束,增加\"" + x + "\",當前用戶賬戶余額為:" + cash);
}
Thread.sleep(10L);
} catch (InterruptedException e) { e.printStackTrace(); }
}
@Override public String toString() { return "User{code='" + code + "', cash=" + cash + '}'; }
}
線程E運行結束,增加"32",當前用戶賬戶余額為:132
線程B運行結束,增加"-60",當前用戶賬戶余額為:72
線程D運行結束,增加"-30",當前用戶賬戶余額為:42
線程F運行結束,增加"21",當前用戶賬戶余額為:63
線程C運行結束,增加"-80",當前用戶賬戶余額為:-17
線程A運行結束,增加"20",當前用戶賬戶余額為:3
Process finished with exit code 0
最終餘額 3 正確,說明同步塊同樣保證了線程安全。
this、私有 final 對象或專用鎖對象,避免用字符串常量或可變對象| 維度 | 同步方法 | 同步代碼塊 |
|---|---|---|
| 語法簡潔性 | 高 | 稍低 |
| 鎖粒度 | 整個方法 | 可精確控制 |
| 性能潛力 | 較低 | 較高 |
| 靈活性 | 固定鎖 this/Class | 可指定任意鎖對象 |