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

之前一直觉得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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值