先说结论:
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();
}
}
}