public class T {
private int count = 10;
private Object o = new Object();
public void m() {
synchronized(o) { //任何線程要執行下面的代碼,必須先拿到o的鎖
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
}
}
synchronized(o) :代表任何線程要執行這行代碼都必須先拿到o對象這把鎖,只有持有o對象鎖的線程才允許執行.如果此時第二個線程進來了,必須等到第一個線程釋放了o這把鎖才
public class T {
private int count = 10;
public void m() {
synchronized(this) { //任何線程要執行下面的代碼,必須先拿到this的鎖
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
}
}
synchronized(this) :指定鎖定自身對象.只有獲取自身對象的鎖才允許進入當前方法
- 等價於如下:
public class T {
private int count = 10;
public synchronized void m() { //等同於在方法的代碼執行時要synchronized(this)
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
}
直接將synchronized加在方法上,注意:synchronized不是鎖定當前方法,而是指鎖定當前對象 類似上面 synchronized(this) 的寫法
public class T {
private static int count = 10;
public synchronized static void m() { //這裏等同於synchronized(yxxy.c_004.T.class)
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
public static void mm() {
synchronized(T.class) { //考慮一下這裏寫synchronized(this)是否可以?
count --;
}
}
}
如果synchronized鎖定的是靜態方法,則鎖定的必須是當前類的class對象.因爲靜態方法是不需要對象訪問的
public class T implements Runnable {
private int count = 10;
public /*synchronized*/ void run() {
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
public static void main(String[] args) {
T t = new T();
for(int i=0; i<5; i++) {
new Thread(t, "THREAD" + i).start();
}
}
}
當我們起5個線程 訪問同一個對象的count值時,如果沒有加鎖,會導致count值爲10時,可能存在多個線程同時-1 多個線程修改之後的結果還是9.要解決這個問題的話,簡單的做法可以直接在方法上加一把鎖.
多線程常見問題一 :同步和非同步方法是否可以同時調用?
public class T {
public synchronized void m1() {
System.out.println(Thread.currentThread().getName() + " m1 start...");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " m1 end");
}
public void m2() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " m2 ");
}
public static void main(String[] args) {
T t = new T();
new Thread(t::m1, "t1").start();
new Thread(t::m2, "t2").start();
}
}
執行上述代碼塊,發現在同步代碼塊執行的時候.非同步方法還是可以執行的.