Synchronized关键字锁的到底是什么(新手入门)

mac2026-09-28  8

之前一直觉得synchronized就是使代码块具有原子性。听了马士兵老师的一个课,说其实锁的是对象,不是很理解。

我的问题是:在下面这个程序里,synchronized到底锁的是整个方法,还是T这个类?

class T{ private int Tcount=10; public synchronized void m1() { while(Tcount>4) { System.out.print(Thread.currentThread()); System.out.println(Tcount); Tcount--; } } }

我通过实验来说明这个问题:

1.我在课程里看他举的例子

在T里定义两个方法m1,m2,m1加锁。

class T{ private int Tcount=10; public synchronized void m1() { while(Tcount>4) { System.out.print(Thread.currentThread()); System.out.println(Tcount); Tcount--; } } public void m2() { while(Tcount>0) { System.out.print(Thread.currentThread()); System.out.println(Tcount); Tcount--; } } }

调用:定义两个线程分别调用m1和m2

public static void main(String args[]) { //MyRunnable mr=new MyRunnable(); T t=new T(); Thread thread=new Thread(t::m1,"m1"); Thread thread2=new Thread(t::m2,"m2"); thread.start(); thread2.start(); }

结果: m1和m2是交叉执行的。这很正常,毕竟第二个线程又没调用m1()对吧。(这个实验很容易误导,让人以为锁的就是m1这个方法。)

2、接下来是重点

如果让m2也加上锁。线程调用不变。

class T{ private int Tcount=10; public synchronized void m1() { while(Tcount>4) { System.out.print(Thread.currentThread()); System.out.println(Tcount); Tcount--; } } public synchronized void m2() { while(Tcount>0) { System.out.print(Thread.currentThread()); System.out.println(Tcount); Tcount--; } } }

如果synchronized锁的是方法,那就应该是T这个类有两个锁,第一把锁m1,第二把锁m2.这样执行结果应该是thread和thread2各不影响。 如果synchronized锁的是类,那就是说如果thread调用了m1(),锁了T这个类,那此时m2()也就不能用了。这样对应的结果就应该是thread执行完,释放了T的锁,thread2才会执行。 进行实验:

public static void main(String args[]) { //MyRunnable mr=new MyRunnable(); T t=new T(); Thread thread=new Thread(t::m1,"m1"); Thread thread2=new Thread(t::m2,"m2"); thread.start(); thread2.start(); }

输出结果: 可以看到,thread和thread2是分开的。

所以Synchronized锁的是T这个类!

但是回到第一个实验,既然m1前加了Synchronized,按这个说法,那T不就被锁了,为什么m2还能被调用? 以下是我的理解: 这是因为m2()这个方法调用的时候根本不需要管它锁没锁。 被Synchronized修饰的方法调用前需要去看看这个类有没有被锁,而没被Synchronized修饰的方法不需要去检查。也就是正确理解一下锁这个类是什么意思。 我的理解,锁这个类其实就是锁的所有被Synchronized关键字修饰的内容。 其实说类也是不准确的,应该说是对象。 每个线程都有自己的堆,是在堆上new出来的那个对象实体上加的锁。 这个也很好做实验:

public static void main(String args[]) { //MyRunnable mr=new MyRunnable(); T t1=new T(); Thread thread=new Thread(t1::m1,"m1"); T t2=new T(); Thread thread2=new Thread(t2::m2,"m2"); thread.start(); thread2.start(); }

得到的结果也是交叉执行的。 —————————————————————————————— 此外,我们知道以下两种写法是等价的。这也说明锁的是this类。

public synchronized void m1() { while(Tcount>4) { System.out.print(Thread.currentThread()); System.out.println(Tcount); Tcount--; } } public void m1() { Synchronized(this){ while(Tcount>4) { System.out.print(Thread.currentThread()); System.out.println(Tcount); Tcount--; } } }
最新回复(0)