先說結論:
1.synchronized加到靜態方法上 調用靜態方法時會鎖住此類,如果此類有2個靜態方法都加上了synchronized則同一時刻只能有一個靜態方法被調用
2.synchronized加到普通方法上 該類的實例(實例指new出來的對象)同一時刻只能調用一個方法,如果多個線程同時調用該實例的多個synchronized方法則只有一個線程會調用到,其他線程會阻塞等待獲取鎖
3.synchronized(obj)放到方法里面作為代碼塊鎖時則要看鎖住的對象是什么:
3.1
如果2個方法里面的代碼塊鎖鎖住的對象是同一個則多個線程調用這2個方法時只有一個線程會調用到,其他線程會阻塞等待,類似於2
中的方法鎖
3.2
如果2個方法里面的代碼塊鎖住的是2個不同的對象則同一時刻允許2個線程同時調用這2個方法,參考下面代碼中Demo類里面的test4和test5
代碼如下:
public class Main {
public static void main(String[] args) {
//java.util.concurrent.CopyOnWriteArrayList
Demo demo = new Demo();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
demo.test3();
Demo.test5();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
demo.test4();
Demo.test6();
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
Demo.test5();
}
});
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
Demo.test6();
}
});
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Demo{
private Object obj1 = new Object();
private Object obj2 = new Object();
public synchronized void test1(){
try {
System.out.println("test1開始執行------"+Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("test1結束執行------"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void test2(){
try {
System.out.println("test2開始執行------"+Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("test2結束執行------"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void test3(){
synchronized (obj1){
try {
System.out.println("test3開始執行------"+Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("test3結束執行------"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void test4(){
synchronized (obj2){
try {
System.out.println("test4開始執行------"+Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("test4結束執行------"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized static void test5(){
try {
System.out.println("test5開始執行------"+Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("test5結束執行------"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized static void test6(){
try {
System.out.println("test6開始執行------"+Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("test6結束執行------"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}