synchronized语法

加在实例方法上

相当于锁住对象本身

public synchronized int getCount() {
       return this.count;
}
//等价于
public int getCount() {
    synchronized (this){
        return this.count;
    }
}

加在静态方法上

相当于锁住类对象

public synchronized static void test(){
    
}

//等价于
public  static void test(){
    synchronized (Main.class){
        
    }
}

所谓的“线程八锁”

就是考察synchronized 锁住的是哪个对象

1

public class Test {
    public static void main(String[] args) {
        Number number = new Number();
        Thread t1 = new Thread() {
            @Override
            public void run() {
                number.a();
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                number.b();
            }
        };

        t1.start();
        t2.start();
    }

}

@Slf4j(topic = "c.Number")
class Number {

    public synchronized void a() {
        log.debug("1");
    }

    public synchronized void b() {
        log.debug("2");
    }

}

a方法和b方法的synchronized 都是锁住当前对象,所以最终打印顺序可能是先1后2,或者先2后1,就看CPU先调度谁

2025-10-11 14:02:06.998 [Thread-0] c.Number - 1
2025-10-11 14:02:07.000 [Thread-1] c.Number - 2
2025-10-11 14:05:44.771 [Thread-1] c.Number - 2
2025-10-11 14:05:44.771 [Thread-0] c.Number - 1

2

public class Test {
    public static void main(String[] args) {
        Number number = new Number();
        Thread t1 = new Thread() {
            @Override
            public void run() {
                number.a();
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                number.b();
            }
        };

        t1.start();
        t2.start();
    }

}

@Slf4j(topic = "c.Number")
class Number {

    public synchronized void a() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.debug("1");
    }

    public synchronized void b() {
        log.debug("2");
    }

}

在情况1的基础上,a方法中sleep一秒,结果可能是:
一秒后打印1、2
或者先打印2,一秒后打印1

2025-10-11 14:20:38.496 [Thread-0] c.Number - 1
2025-10-11 14:20:38.496 [Thread-1] c.Number - 2
2025-10-11 14:22:53.209 [Thread-1] c.Number - 2
2025-10-11 14:22:54.221 [Thread-0] c.Number - 1

3

public class Test {
    public static void main(String[] args) {
        Number number = new Number();
        Thread t1 = new Thread() {
            @Override
            public void run() {
                number.a();
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                number.b();
            }
        };

        Thread t3 = new Thread() {
            @Override
            public void run() {
                number.c();
            }
        };

        t1.start();
        t2.start();
        t3.start();


    }

}

@Slf4j(topic = "c.Number")
class Number {

    public synchronized void a() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.debug("1");
    }

    public synchronized void b() {
        log.debug("2");
    }

    public void c() {
        log.debug("3");
    }

}

在情况2的基础上,加了个c方法,没有synchronized。
线程在调用c方法的时候不需要获得锁,也就没有互斥效果。
3一定比1先打印,至于2,取决于cpu的调度。

结果可能是:
3、1秒后1、2
3、2、1秒后1
2、3、1秒后1

2025-10-11 14:43:59.073 [Thread-2] c.Number - 3
2025-10-11 14:44:00.082 [Thread-0] c.Number - 1
2025-10-11 14:44:00.082 [Thread-1] c.Number - 2
2025-10-11 14:44:51.578 [Thread-1] c.Number - 2
2025-10-11 14:44:51.578 [Thread-2] c.Number - 3
2025-10-11 14:44:52.581 [Thread-0] c.Number - 1
2025-10-11 14:49:49.206 [Thread-2] c.Number - 3
2025-10-11 14:49:49.206 [Thread-1] c.Number - 2
2025-10-11 14:49:50.214 [Thread-0] c.Number - 1

4

public class Test {
    public static void main(String[] args) {
        Number n1 = new Number();
        Number n2 = new Number();
        Thread t1 = new Thread() {
            @Override
            public void run() {
                n1.a();
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                n2.b();
            }
        };

        t1.start();
        t2.start();


    }

}

@Slf4j(topic = "c.Number")
class Number {

    public synchronized void a() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.debug("1");
    }

    public synchronized void b() {
        log.debug("2");
    }

}

这种情况下,线程1和线程2锁住的是不同的对象,相当于没有锁,所以一定是先打印2,1秒后打印1。

2025-10-11 14:51:08.810 [Thread-1] c.Number - 2
2025-10-11 14:51:09.818 [Thread-0] c.Number - 1

5

public class Test {
    public static void main(String[] args) {
        Number n1 = new Number();
        Thread t1 = new Thread() {
            @Override
            public void run() {
                n1.a();
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                n1.b();
            }
        };

        t1.start();
        t2.start();


    }

}

@Slf4j(topic = "c.Number")
class Number {

    public static synchronized void a() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.debug("1");
    }

    public synchronized void b() {
        log.debug("2");
    }

}

a方法变为静态方法,锁住的是类对象,b方法还是实例方法,锁住的是当前对象,线程1和线程2锁住的是不同的对象,相当于没有锁,所以一定是先打印2,1秒后打印1。

2025-10-11 14:56:48.641 [Thread-1] c.Number - 2
2025-10-11 14:56:49.646 [Thread-0] c.Number - 1

6

public class Test {
    public static void main(String[] args) {
        Number n1 = new Number();
        Thread t1 = new Thread() {
            @Override
            public void run() {
                n1.a();
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                n1.b();
            }
        };

        t1.start();
        t2.start();


    }

}

@Slf4j(topic = "c.Number")
class Number {

    public static synchronized void a() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.debug("1");
    }

    public static synchronized void b() {
        log.debug("2");
    }

}

a和b都是静态方法,也就是锁住的是同一个对象,所以打印顺序取决于CPU调度顺序,和情况1一样。

2025-10-11 15:00:22.546 [Thread-1] c.Number - 2
2025-10-11 15:00:23.547 [Thread-0] c.Number - 1
2025-10-11 15:02:33.079 [Thread-0] c.Number - 1
2025-10-11 15:02:33.083 [Thread-1] c.Number - 2

7

public class Test {
    public static void main(String[] args) {
        Number n1 = new Number();
        Number n2 = new Number();

        Thread t1 = new Thread() {
            @Override
            public void run() {
                n1.a();
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                n2.b();
            }
        };

        t1.start();
        t2.start();


    }

}

@Slf4j(topic = "c.Number")
class Number {

    public static synchronized void a() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.debug("1");
    }

    public synchronized void b() {
        log.debug("2");
    }

}

锁住不同对象,没有互斥,一定是先2,1秒后1。

2025-10-11 15:04:10.898 [Thread-1] c.Number - 2
2025-10-11 15:04:11.918 [Thread-0] c.Number - 1

8

public class Test {
    public static void main(String[] args) {
        Number n1 = new Number();
        Number n2 = new Number();

        Thread t1 = new Thread() {
            @Override
            public void run() {
                n1.a();
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                n2.b();
            }
        };

        t1.start();
        t2.start();


    }

}

@Slf4j(topic = "c.Number")
class Number {

    public static synchronized void a() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.debug("1");
    }

    public static synchronized void b() {
        log.debug("2");
    }

}

a和b都是静态方法,锁住的都是类对象,虽然创建了不同的实例对象调用方法,但是锁住的是同一个对象。结果还是取决于CPU先调度谁。

2025-10-11 15:06:57.817 [Thread-1] c.Number - 2
2025-10-11 15:06:58.832 [Thread-0] c.Number - 1
2025-10-11 15:09:30.331 [Thread-0] c.Number - 1
2025-10-11 15:09:30.331 [Thread-1] c.Number - 2

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐