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
3641

被折叠的 条评论
为什么被折叠?



