java中synchronized的普通方法与静态方法获取的锁对象是什么
2018-01-20 16:43
429 查看
好久没有复习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.普通方法
结果:
2.静态方法
诸位有兴趣的可以自行粘贴到本地进行验证。
说到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的输出并未出现乱序情况,表明其确实实现了同步。
诸位有兴趣的可以自行粘贴到本地进行验证。
相关文章推荐
- (Java多线程)分析静态方法所适用的同步监视器对象是什么?
- Java的synchronized加在方法上或者对象上有什么区别?
- Java面向对象-static静态方法与普通方法
- java synchronized修饰普通方法,修饰静态方法,修饰代码块,修饰线程run方法 比较
- Java: synchronized详解,静态同步方法,普通同步方法,同步代码块
- java synchronized修饰普通方法,修饰静态方法,修饰代码块,修饰线程run方法 比较
- java开发中利用反射获取对象静态的方法
- Java的synchronized加在方法上或者对象上有什么区别?
- Java面向对象-static关键字、静态方法与普通方法、静态成员变量
- Java:使用 synchronized和Lock对象获取对象锁
- Java中获取Class对象的三种方法
- java中静态变量和静态方法分别有什么特点?
- 从JVM内存管理的角度谈谈静态方法和静态属性 和 java对象引用与JVM自动内存管理
- Java网络编程从入门到精通(2):创建InetAddress对象的四个静态方法
- Java:使用synchronized和Lock对象获取对象锁
- java 类调用静态方法不需要实际对象存在吗,仅仅将类装载到内存中就可以了吗
- 关于Java的泛型在所声明的对象中如何获取class或者实例的方法的总结
- Java在静态方法中可通过对象访问其私有方法
- java中获取Class对象的几种方法
- java中静态变量和静态方法分别有什么特点?