Java线程和多线程(十四)——Synchronized关键字解析
来源:互联网 发布:好吃的肉类零食知乎 编辑:程序博客网 时间:2024/06/06 17:46
曾经有一个比较有趣的面试问题,那就是,关于使用synchronized
关键字,是用在方法上面尾号,还是用在一个代码块上面为好?
答案就是使用锁定代码块为更好。因为这样不会锁定对象。当synchronized
关键字在实例方法的上面时,线程对于该方法的访问会直接锁定整个对象,参考如下代码:
class Sync { public synchronized void syncMethod() { System.out.println("Sync Method Executed"); } public void syncThis() { synchronized (this) { System.out.println("Sync This Executed"); } }}
上面的类中,syncMethod()
和syncThis()
方法,是没有区别的。为了验证这个说法,参考如下代码:
package net.ethanpark.common.task;/** * Author: EthanPark <br/> * Date: 2016/11/27<br/> */public class SyncTest { public static void main(String[] args) { Sync sync = new Sync(); Thread t1 = new Thread(new Runnable() { @Override public void run() { sync.syncMethod(); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { sync.syncThis(); } }); t1.start(); t2.start(); }}class Sync { public synchronized void syncMethod() { System.out.println("Sync Method Start To Executed"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Sync Method Executed"); } public void syncThis() { synchronized (this) { System.out.println("Sync This Executed"); } }}
再说上面的代码中,我启动了两个线程,分别执行syncMethod()
和syncThis()
方法,其中syncMethod()
方法会等待5秒,然后才执行结束。以下是输出的结果:
Sync Method Start To ExecutedSync Method ExecutedSync This Executed
t1和t2是先后启动的,如果syncMethod()
方法没有锁定Sync对象的话,syncThis()
方法肯定会更优先的执行,但是syncThis()
方法从输出来看,在获取this
对象的锁的时候,阻塞了,直到syncMethod()
全部执行完毕才开始执行,所以才有如上的输出。
在考虑前面那个问题就清晰了,synchronized
直接加在方法上面,会锁定整个对象,也就是说,如果对象中有一些字段是不需要同时来同步的,synchronized
关键字也会阻止其他线程来获取该对象的锁,从而令其他线程阻塞而无法达到高吞吐量。
当然,synchronized
关键字对对象加锁,也只有其他对象也在请求对象锁的时候才会阻塞的,如果其他对象不需要请求对象锁,而是直接访问非同步变量,还是允许的。针对之前的代码我增加了一个新的线程和一个新的方法notSyncMethod()
:
package net.ethanpark.common.task;/** * Author: EthanPark <br/> * Date: 2016/11/27<br/> */public class SyncTest { public static void main(String[] args) { Sync sync = new Sync(); Thread t1 = new Thread(new Runnable() { @Override public void run() { sync.syncMethod(); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { sync.syncThis(); } }); Thread t3 = new Thread(new Runnable() { @Override public void run() { sync.notSyncMethod(); } }); t1.start(); t2.start(); t3.start(); }}class Sync { public synchronized void syncMethod() { System.out.println("Sync Method Start To Executed"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Sync Method Executed"); } public void syncThis() { synchronized (this) { System.out.println("Sync This Executed"); } } public void notSyncMethod(){ System.out.println("Not Sync Method Executed"); }}
程序的输出如下:
Sync Method Start To ExecutedNot Sync Method ExecutedSync Method ExecutedSync This Executed
从第一行输出来看,t1其实已经获得了sync
对象的对象锁,但是notSyncMethod()
方法仍然是可以执行的。
需要注意的是,synchronized
方法也是可以加在静态方法上面的。然而加在静态方法上面和加在实例方法上面,两者是不会使得线程互斥的。原因很简单,针对实例方法同步,我们请求的是对象锁,而静态方法的访问,是不针对对象的,所以两者是不会冲突的。针对静态方法的同步,实际上跟针对类型的同步是一致的。参考如下代码:
package net.ethanpark.common.task;/** * Author: EthanPark <br/> * Date: 2016/11/27<br/> */public class SyncTest { public static void main(String[] args) { Sync sync = new Sync(); Thread t1 = new Thread(new Runnable() { @Override public void run() { sync.syncMethod(); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { Sync.staticSyncMethod(); } }); Thread t3 = new Thread(new Runnable() { @Override public void run() { Sync.staticTypeMethod(); } }); t1.start(); t2.start(); t3.start(); }}class Sync { public synchronized void syncMethod() { System.out.println("Sync Method Start To Executed"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Sync Method Executed"); } public synchronized static void staticSyncMethod(){ System.out.println("Static Sync Method Start To Executed"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Static Sync Method Executed"); } public static void staticTypeMethod(){ synchronized (Sync.class){ System.out.println("Static Sync Type Executed"); } }}
上面代码的输出如下:
Sync Method Start To ExecutedStatic Sync Method Start To ExecutedStatic Sync Method ExecutedStatic Sync Type ExecutedSync Method Executed
可以看出,在staticSyncMethod()
和staticTypeMethod()
两者是等同的,当staticSyncMethod()
执行的时候,staticTypeMethod()
是阻塞的。而两个静态的方法,跟实例的方法是完全互不影响的。
- Java线程和多线程(十四)——Synchronized关键字解析
- Java多线程:线程同步与关键字synchronized
- Java 多线程 —— synchronized关键字
- Java多线程——关键字synchronized
- Java多线程—— synchronized关键字详解
- Java对象锁和类锁全面解析(多线程synchronized关键字)
- Java对象锁和类锁全面解析(多线程synchronized关键字)
- Java对象锁和类锁全面解析(多线程synchronized关键字)
- java对象锁和类锁全面解析(多线程synchronized关键字)
- Java对象锁和类锁全面解析(多线程synchronized关键字)
- Java对象锁和类锁全面解析(多线程synchronized关键字)
- Java对象锁和类锁全面解析(多线程synchronized关键字)
- Java对象锁和类锁全面解析(多线程synchronized关键字)
- Java多线程(六)——Synchronized关键字
- Java多线程(3)——同步与synchronized关键字
- java多线程之synchronized和volatile关键字
- Java多线程 synchronized关键字
- Java多线程-synchronized关键字
- [LeetCode]Simplify Path
- 【HTML5】画小猫咪
- Shell script执行方式
- 终极肖像美容润饰PS动作
- 基于svm的中文文本自动分类系统
- Java线程和多线程(十四)——Synchronized关键字解析
- css 左边固定宽度,右边自动填充的布局,不用flex
- 2016年10月27日Ramesh Contest
- 转发与重定向
- 链队列介绍及其C++实现
- 棋盘村
- Atitit 发帖机系列(8) 词法分析器v5 版本新特性说明)
- AndroidBug相关博客收藏
- add fedora aliyun