关于synchronized的几种用法和相关知识。
来源:互联网 发布:java高手的简历 编辑:程序博客网 时间:2024/06/07 13:49
synchronized,是java中多线程编程重要的内容,而在应用中多线程并发更是必不可少的,那么对于synchronized,我把这几天学习的内容记录下来。
synchronized是一种加锁同步机制,这就好比一栋房子只有一把钥匙,而只有拥有这把钥匙的人才能够进入,在出来之后,再将钥匙放置原处,等待下一个人来拿。在这种机制下,我们的多线程安全也就有了保证。
那么synchronized有几种用法,下面来看一看。
如果我们创建两个线程,分别调用test1和test2,下面来看结果。
可以看到,二者交替执行,并没有实现同步。出现这种情况的原因主要是因为普通方法和静态方法的引用的锁不是同一把。
我们把test1也改成static修饰的方法试试。
可以看到两个方法依次执行,说明我们同一个类中所有的以static修饰的方法,加上synchronized关键字,引用的是同一把class锁。
通过上面两个实验证明,synchronized关键字在修饰方法时
1,普通方法引用的是方法所在类的对象锁。
2,静态方法引用的是方法所在类的类锁。
问题:如果两个static方法不在同一个类中呢,会不会实现同步呢?请小伙伴们思考。
好了,说完了synchronized修饰方法之后,我们再来谈谈synchronized修饰代码块。
为什么会出现既可以修饰方法又可以修饰代码块的情况呢?
我们上面已经知道,不论是否static修饰的同步方法,都是引用的方法所在类的锁,那么如果该类中有很多synchronized修饰的方法,而恰巧此时进入的线程执行的操作时长过长或者是死循环,那么对于其他等待进入该类中的线程造成了长时间的等待,这对于系统是致命的,所以我们可以使用synchronized修饰代码块的方式来缩小同步的范围,最大化地提升系统的性能。这就好比我们在游乐场玩的滑行索道,为了保证安全,通常情况下是在前一个人到达地面的时候才允许后面的人开始向下滑行,而如果将索道从中间一分为二,那么前一个人在换到第二条索道时,后面的人就可以从第一条索道向下滑行,从而就减少了后面的人等待的时间。
那么synchronized修饰代码块应该注意什么呢。
来看结果
同样做到了同步,这其实刚才已经说过了,test1中引用的是类.class ,而test2虽然不能指定引用对象,但它其实同样引用了类.class 。
那如果我将上面例子中的SynchTest.class换成SynchTest.this。
那这样的话就不能实现同步了。
再如果我将上面例子test2的static修饰去掉呢?对,同样无法同步。
说到这里,想必明白一些了,其实可以总结一下几点:
1,synchronized修饰普通方法时,引用的是方法所在类的对象。
2,synchronized修饰static方法时,引用的是方法所在类的class。
3,synchronized修饰代码块时,括号中的对象一致时,则会形成互斥。
4,在使用synchronized时,尽量缩小其影响范围。
synchronized是一种加锁同步机制,这就好比一栋房子只有一把钥匙,而只有拥有这把钥匙的人才能够进入,在出来之后,再将钥匙放置原处,等待下一个人来拿。在这种机制下,我们的多线程安全也就有了保证。
那么synchronized有几种用法,下面来看一看。
1,synchronized修饰普通方法与静态方法。
public synchronized void test1(){ String name = Thread.currentThread().getName(); for (int i = 0; i < 4; i++) { try { Log.e("test1",name); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } public static synchronized void test2(){ String name = Thread.currentThread().getName(); for (int i = 0; i < 4; i++) { try { Log.e("test2",name); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }
如果我们创建两个线程,分别调用test1和test2,下面来看结果。
test1: Thread-795test2: Thread-796test2: Thread-796test1: Thread-795test2: Thread-796test2: Thread-796test1: Thread-795test1: Thread-795
可以看到,二者交替执行,并没有实现同步。出现这种情况的原因主要是因为普通方法和静态方法的引用的锁不是同一把。
我们把test1也改成static修饰的方法试试。
test1: Thread-801test1: Thread-801test1: Thread-801test1: Thread-801test2: Thread-802test2: Thread-802test2: Thread-802test2: Thread-802
可以看到两个方法依次执行,说明我们同一个类中所有的以static修饰的方法,加上synchronized关键字,引用的是同一把class锁。
通过上面两个实验证明,synchronized关键字在修饰方法时
1,普通方法引用的是方法所在类的对象锁。
2,静态方法引用的是方法所在类的类锁。
问题:如果两个static方法不在同一个类中呢,会不会实现同步呢?请小伙伴们思考。
好了,说完了synchronized修饰方法之后,我们再来谈谈synchronized修饰代码块。
为什么会出现既可以修饰方法又可以修饰代码块的情况呢?
我们上面已经知道,不论是否static修饰的同步方法,都是引用的方法所在类的锁,那么如果该类中有很多synchronized修饰的方法,而恰巧此时进入的线程执行的操作时长过长或者是死循环,那么对于其他等待进入该类中的线程造成了长时间的等待,这对于系统是致命的,所以我们可以使用synchronized修饰代码块的方式来缩小同步的范围,最大化地提升系统的性能。这就好比我们在游乐场玩的滑行索道,为了保证安全,通常情况下是在前一个人到达地面的时候才允许后面的人开始向下滑行,而如果将索道从中间一分为二,那么前一个人在换到第二条索道时,后面的人就可以从第一条索道向下滑行,从而就减少了后面的人等待的时间。
那么synchronized修饰代码块应该注意什么呢。
我将test1循环打印的部分使用synchronized (SynchTest.class)修饰,注意:这里使用的关键字是所在类.class
public void test1(){ String name = Thread.currentThread().getName(); synchronized (SynchTest.class){ for (int i = 0; i < 4; i++) { try { Log.e("test1",name); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static synchronized void test2(){ String name = Thread.currentThread().getName(); for (int i = 0; i < 4; i++) { try { Log.e("test2",name); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }
来看结果
test1: Thread-813test1: Thread-813test1: Thread-813test1: Thread-813test2: Thread-814test2: Thread-814test2: Thread-814test2: Thread-814
同样做到了同步,这其实刚才已经说过了,test1中引用的是类.class ,而test2虽然不能指定引用对象,但它其实同样引用了类.class 。
那如果我将上面例子中的SynchTest.class换成SynchTest.this。
那这样的话就不能实现同步了。
再如果我将上面例子test2的static修饰去掉呢?对,同样无法同步。
说到这里,想必明白一些了,其实可以总结一下几点:
1,synchronized修饰普通方法时,引用的是方法所在类的对象。
2,synchronized修饰static方法时,引用的是方法所在类的class。
3,synchronized修饰代码块时,括号中的对象一致时,则会形成互斥。
4,在使用synchronized时,尽量缩小其影响范围。
以上就是我学习的内容,欢迎各位大神指正补充。
阅读全文
0 0
- 关于synchronized的几种用法和相关知识。
- 关于字符集和Unicode的相关知识
- 关于字符集和Unicode的相关知识
- 关于坐标系和投影的相关知识
- 关于@synchronized(self)的用法
- 关于@synchronized(self)的用法
- 关于@synchronized(self)的用法
- 关于@synchronized(self)的用法
- 关于@synchronized(self)的用法
- 关于@synchronized(self)的用法
- 关于@synchronized(self)的用法
- 关于@synchronized(self)的用法
- 关于几种无线知识的介绍
- java关于synchronized的某些知识
- 关于synchronized的几点说明
- synchronized的用法和原理
- Java【多线程知识总结(7)】多线程同步问题-关于synchronized代码块和synchronized方法的应用
- 关于java中的synchronized的用法
- 数据结构排序算法代码实现
- java反射总结
- 2017-12-21
- HQL (迫切)左外连接
- adobe flash builder flex 4.6 下载地址
- 关于synchronized的几种用法和相关知识。
- windows命令行方式下打印和设置PATH变量
- SecureRandom实现随机盐salt
- Fragment 生命周期的详情
- ROS -Kinetic<在ubuntu16.04上安装rbx1和arbotix模拟器>
- 用java实现的通用内存分页函数
- SQL事务中锁的用法,与结束进程语句的用法
- JAVA/JS 转码解码(URLEncoder.encode | URLDecoder.decode | encodeURIComponent | decodeURIComponent)
- 【Python学习笔记(三)】:爬虫用到的知识点总结