java中synchronized的普通方法与静态方法获取的锁对象是什么

2 篇文章 0 订阅

好久没有复习java多线程相关知识点了,在此对自己的一些思考做一个记录。

说到java多线程,最有名的就是synchronized关键字了。

一.synchronized关键字的实现原理

java程序运行时所有的对象都存储在JVM中,而在JVM中所有的对象都可以作为内置锁对象。

synchronized修饰的不论是方法还是代码块都表明其中的内容想要执行,必须先获取对象的内置锁才行。因此synchronized获取的代码块中锁定的对象不能为null。

synchronized方法不能阻止其他线程通过普通方法(非线程安全方法)去访问修改其修饰的对象,所以我们需要将所有涉及到修改同一对象的操作都用synchronized进行修饰。

二.synchronized用法

synchronized关键字可用于修饰代码块普通方法静态方法synchronized修饰代码块的时候其可以获取内置锁的对象包括this、XXX.class以及其他对象。

其中根据JVM内存原理,可以明确this与XXX.class不是一个对象。this指向的是该类通过new创建一个新对象后的映射;XXX.class等效于this.getClass(),即其指向的都是java运行时加载在栈中的类型。

三.synchronized修饰的普通方法与静态方法分别获取了什么对象的内置锁呢?

答案是synchronized修饰的普通方法获取的是等效于this的指向对象的内置锁,即新创建的对象本身;synchronized修饰的静态方法获取的是该方法所在类的内置锁,即XXX.class

四.问题三的验证代码与结果

1.普通方法

public class Test {
	public static void main(String[] args) {
		final Test test = new Test();
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say1();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say2();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say1();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say2();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say1();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say2();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say1();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say2();
			}
		}).start();
	}
	
	private static String name = "ajajajaj";
	
	public synchronized void say1(){
		System.out.println("R1");
		int miao = 0;
		for(int i  = 0 ;i < 10000000; ++ i){
			miao = i;
		}
		System.out.println(Test.class + "start1");
		miao = 0;
		for(int i  = 0 ;i < 10000000; ++ i){
			miao = i;
		}
		System.out.println("miao1");
	}
	
	public void say2(){
		System.out.println("R2");
		int miao = 0;
		for(int i  = 0 ;i < 10000000; ++ i){
			miao = i;
		}
		synchronized (this) {
			System.out.println(Test.class + "start2");
			miao = 0;
			for(int i  = 0 ;i < 10000000; ++ i){
				miao = i;
			}
			System.out.println("miao2");
		}
	
	}
}

结果:

R1
R2
class com.thread.Teststart1
R2
R1
miao1
R1
class com.thread.Teststart1
miao1
class com.thread.Teststart1
miao1
R2
class com.thread.Teststart2
R1
miao2
class com.thread.Teststart2
R2
miao2
class com.thread.Teststart2
miao2
class com.thread.Teststart2
miao2
class com.thread.Teststart1
miao1

2.静态方法

public class Test {
	public static void main(String[] args) {
		final Test test = new Test();
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say1();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say2();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say1();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say2();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say1();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say2();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say1();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.say2();
			}
		}).start();
	}
	
	private static String name = "ajajajaj";
	
	public synchronized static void say1(){
		System.out.println("R1");
		int miao = 0;
		for(int i  = 0 ;i < 10000000; ++ i){
			miao = i;
		}
		System.out.println(Test.class + "start1");
		miao = 0;
		for(int i  = 0 ;i < 10000000; ++ i){
			miao = i;
		}
		System.out.println("miao1");
	}
	
	public void say2(){
		System.out.println("R2");
		int miao = 0;
		for(int i  = 0 ;i < 10000000; ++ i){
			miao = i;
		}
		synchronized (this.getClass()) {
			System.out.println(Test.class + "start2");
			miao = 0;
			for(int i  = 0 ;i < 10000000; ++ i){
				miao = i;
			}
			System.out.println("miao2");
		}
	
	}
}
结果:

R1
R2
class com.thread.Teststart1
miao1
R1
class com.thread.Teststart1
miao1
class com.thread.Teststart2
miao2
R2
R1
class com.thread.Teststart1
miao1
R1
class com.thread.Teststart1
miao1
R2
class com.thread.Teststart2
miao2
R2
class com.thread.Teststart2
miao2
class com.thread.Teststart2
miao2
可以从结果中看出class com.thread.Teststart与miao的输出并未出现乱序情况,表明其确实实现了同步。


诸位有兴趣的可以自行粘贴到本地进行验证。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值