Java面试之synchronized 和 static synchronized
面试题:
答案:
不能
不能
不能
不能
能
正文
概述
通过分析这两个用法的分析,我们可以理解java中锁的概念。一个是实例锁(锁在某一个实例对象上,如果该类是单例,那么该锁也具有全局锁的概念),一个是全局锁(该锁针对的是类,无论实例多少个对象,那么线程都共享该锁)。实例锁对应的就是synchronized关键字,而类锁(全局锁)对应的就是static synchronized(或者是锁在该类的class或者classloader对象上)。
区别
synchronized关键字
synchronized作用是对类的当前实例(对象)加锁。可以使用synchronized关键字来标记一个方法或者代码块,当某个线程调用该对象的synchronized方法或者访问synchronized代码块时,这个线程便获得了该对象的锁,其他线程暂时无法访问这个方法,只有等待这个方法执行完毕或者代码块执行完毕,这个线程才会释放该对象的锁(Java 并发编程)。
synchronized代码块【synchronized(synObject)】使用起来比synchronized方法要灵活得多。因为也许一个方法中只有一部分代码只需要同步,如果此时对整个方法用synchronized进行同步,会影响程序执行效率。而使用synchronized代码块就可以避免这个问题(同步对象或类属性),synchronized代码块可以实现只对需要同步的地方进行同步。
与Lock的区别:1. synchronized是Java语言的关键字,因此是内置特性,Lock是一个类(java.util.concurrent.locks包),通过这个类可以实现同步访问;2. synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用。Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。
static synchronized:
每个类有一个锁,它可以用来控制对static数据成员的并发访问。访问static synchronized方法占用的是类锁,而访问非static synchronized方法占用的是对象锁。
static synchronized控制类的所有实例(对象)的访问(相应代码块)。synchronized相当于 this.synchronized,static synchronized相当于Something.synchronized
一个日本作者-结成浩的《java多线程设计模式》有这样的一个列子:
pulbic class Something(){
public synchronized void isSyncA(){}
public synchronized void isSyncB(){}
public static synchronized void cSyncA(){}
public static synchronized void cSyncB(){}
}
那么,假如有Something类的两个实例x与y,那么下列各组方法被多线程同时访问的情况是怎样的?
a. x.isSyncA()与x.isSyncB()
b. x.isSyncA()与y.isSyncA()
c. x.cSyncA()与y.cSyncB()
d. x.isSyncA()与Something.cSyncA()
这里,很清楚的可以判断:
都是对同一个实例(x)的synchronized域访问,因此不能被同时访问。(多线程中访问x的不同synchronized域不能同时访问)
如果在多个线程中访问x.isSyncA(),因为仍然是对同一个实例,且对同一个方法加锁,所以多个线程中也不能同时访问。(多线程中访问x的同一个synchronized域不能同时访问)
是针对不同实例的,因此可以同时被访问(对象锁对于不同的对象实例没有锁的约束)
因为是static synchronized,所以不同实例之间仍然会被限制,相当于Something.isSyncA()与 Something.isSyncB()了,因此不能被同时访问。
书上的 答案是可以被同时访问的,答案理由是synchronzied的是实例方法与synchronzied的类方法由于锁定(lock)不同的原因。
个人分析也就是synchronized 与static synchronized 相当于两帮派,各自管各自,相互之间就无约束了,可以被同时访问。
举个例子:
public class TestSynchronized {
public synchronized void test1() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
} public static synchronized void test2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
} public static void main(String[] args) {
final TestSynchronized myt2 = new TestSynchronized();
Thread test1 = new Thread(new Runnable() {
public void run() {
myt2.test1();
}
}, "test1");
Thread test2 = new Thread(new Runnable() {
public void run() {
TestSynchronized.test2();
}
}, "test2");
test1.start();
test2.start();
}
}
test1 : 4
test2 : 4
test1 : 3
test2 : 3
test2 : 2
test1 : 2
test2 : 1
test1 : 1
test1 : 0
test2 : 0
上面代码synchronized同时修饰静态方法和实例方法,但是运行结果是交替进行的,这证明了类锁和对象锁是两个不一样的锁,控制着不同的区域,它们是互不干扰的。同样,线程获得对象锁的同时,也可以获得该类锁,即同时获得两个锁,这是允许的。
结论
A: synchronized static是某个类的范围,synchronized static cSync{}防止多个线程中多个实例同时访问这个 类中的synchronized static 方法。它可以对类的所有对象实例起作用。
B: synchronized 是某实例的范围,synchronized isSync(){}防止多个线程中这一个实例同时访问这个类的synchronized 方法。
其实总结起来很简单。
一个锁的是类对象,一个锁的是实例对象。
若类对象被lock,则类对象的所有同步方法全被lock;
若实例对象被lock,则该实例对象的所有同步方法全被lock。
Java面试之synchronized 和 static synchronized的更多相关文章
- synchronized与static synchronized 的差别、synchronized在JVM底层的实现原理及Java多线程锁理解
本Blog分为例如以下部分: 第一部分:synchronized与static synchronized 的差别 第二部分:JVM底层又是怎样实现synchronized的 第三部分:Java多线程锁 ...
- 浅析Java中synchronized与static synchronized
synchronized关键字 synchronized是进行同步处理而保证线程安全.在一个方法中,如果是方法内的私有变量,那个这个变量是线程安全的,但是类中的实例变量是可能会出现线程安全问题的,当多 ...
- Synchronized和Static Synchronized区别
通过分析这两个用法的分析,我们可以理解Java中锁的概念. 一个是实例锁(锁在某一个实例对象上,如果该类是单例,那么该锁也具有全局锁的概念), 一个是全局锁(该锁针对的是类,无论实例多少个对象,那么线 ...
- [Android Pro] synchronized与static synchronized 的区别
reference to : http://www.cnblogs.com/shipengzhi/articles/2223100.html 1.synchronized与static synchr ...
- synchronized和static synchronized的比较
群里讨论的一个问题,网上别人已经贴出了很详细的说明,这里补充记录下,后面加入个人测试代码. 起因:1月份的时候看群里讨论一道问题,问题内容如下: 一个日本作者-结成浩的<java多线程设计模式& ...
- synchronized与static synchronized 差异
1.synchronized与static synchronized 差异 synchronized是对类的当前实例进行加锁,防止其它线程同一时候訪问该类的该实例的全部synchroniz ...
- 多线程同步锁和死锁以及synchronized与static synchronized 的区别
线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程.一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序.简而言之:一个程序运行后至少有一个进程,一个进程 ...
- synchronized与static synchronized 的区别
synchronized是对类的当前实例加锁,防止其他线程同时访问该类的该实例的synchronized块,这里的概念是“类的当前实例”,而static synchronized是对类的所有实例加锁, ...
- java面试:关于public static void main(String[] args)是什么意思?
它是作为JAVA中的主函数,所有java程序的运行起点就是这个方法,除了args这个名字可以不一样外,其他必须是这样. 主函数的一般写法如下: public static void main(Stri ...
随机推荐
- ansible 流程控制
ansible 流程控制 使用when判断主机名 - hosts: rsync_server tasks: - name: Install rsyncd Server yum: name: rsync ...
- SPA项目开发之登录
前端 首先安装开发模板 npm install element-ui -S npm install axios -S npm install qs -S npm install vue-axios - ...
- rowKey原则
rowKey设计原则 1.长度原则 最大值为64KB, 长度在10 ~ 100byte ; 最好是 8 的倍数,太长会影响性能: 2.唯一原则 具有唯一性: 3.散列原则 1).盐值散列:不能使用时间 ...
- SQL查询--内连接、外连接、自连接查询
先创建2个表:学生表和教师表 1.内连接: 在每个表中找出符合条件的共有记录.[x inner join y on...] 第一种写法:只用where SELECT t.TEACHER_NAME, ...
- 【STM32H7教程】第31章 STM32H7的USART应用之RS485
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第31章 STM32H7的USART应用之RS48 ...
- 持续集成(CI):WEB自动化+Allure+Jenkins定时构建
一.allure插件安装 pytest可以通过allure集成展示优美的测试报告,同样allure也可以与Jenkins集成,并且Jenkins有构建记录,所以可以看到历史构建曲线图,通过曲线图可以清 ...
- Protractor - 怎样运行
前一篇设置好了Protractor基本运行环境,那怎样运行Protractor呢? 要运行我们的测试脚本,至少需要配置好两个文件: ---Package.json ---conf.js Package ...
- c++11 C++14 C++17
Since C++11, WG21, the ISO designation for the C++ standard, try to shipped the standard every 3 ye ...
- Python中全局变量的引用与修改之格式影响
先来看下面的代码及执行结果: a = 1 b = [2,3] def nums(): a = 2 b[0] = 0 print(a) print(b) print(a) print(b) nums() ...
- 解决pip使用异常No module named 'pip'
场景 在使用pip进行升级时 python install --upgrade named pip 时提示: No module named pip 注: 博客: https://blog.csdn. ...