java中synchronized 用在实例方法和对象方法上面的区别
https://bijian1013.iteye.com/blog/1836575
在Java中,synchronized 是用来表示同步的,我们可以synchronized 来修饰一个方法。也可以synchronized 来修饰方法里面的一个语句块。
修饰实例方法:
- public synchronized void normalMethod() throws InterruptedException {
- for (int i = 0; i < 10; i++) {
- Thread.sleep(1000);
- System.out.println("normalMethod:" + i);
- }
- }
修饰类方法(static 方法):
- public static synchronized void staticMethod() throws InterruptedException {
- for (int i = 0; i < 10; i++) {
- Thread.sleep(500);
- System.out.println("staticMethod:" + i);
- }
- }
修饰方法里面语句块:
- public static void staticMethod() throws InterruptedException {
- synchronized (locks) {
- for (int i = 0; i < 10; i++) {
- Thread.sleep(1000);
- System.out.println("staticMethod:" + i);
- }
- }
- }
注意:这里不能用synchronized修饰方法外面的语句块(我把他叫做类语句块),虽然我们可以在方法外面定义语句块,这样做会遇到编译错误,这里涉及到了Java里面的对象初始化的部分知识。大概的原因就是synchronized锁住的是对象,当初始化对象的时候,JVM在对象初始化完成之前会调用方法外面的语句块,这个时候对象还不存在,所以就不存在锁了。
那么,在static方法和非static方法前面加synchronized到底有什么不同呢?
static的方法属于类方法,它属于这个Class(注意:这里的Class不是指Class的某个具体对象),那么static获取到的锁,就是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。而非static方法获取到的锁,就是当前调用这个方法的对象的锁了。所以,他们之间不会产生互斥。
实例1:
- package com.bijian.thread;
- public class SynchronizedTest {
- public static synchronized void staticMethod() throws InterruptedException {
- for (int i = 0; i < 10; i++) {
- Thread.sleep(500);
- System.out.println("staticMethod:" + i);
- }
- }
- public synchronized void normalMethod() throws InterruptedException {
- for (int i = 0; i < 10; i++) {
- Thread.sleep(1000);
- System.out.println("normalMethod:" + i);
- }
- }
- public static void main(String[] args) {
- final SynchronizedTest synchronizedTest = new SynchronizedTest();
- Thread thread = new Thread(new Runnable() {
- public void run() {
- try {
- synchronizedTest.normalMethod();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }, "a");
- Thread thread1 = new Thread(new Runnable() {
- public void run() {
- try {
- SynchronizedTest.staticMethod();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }, "b");
- thread1.start();
- thread.start();
- }
- }
运行结果:
- staticMethod:0
- normalMethod:0
- staticMethod:1
- staticMethod:2
- normalMethod:1
- staticMethod:3
- staticMethod:4
- normalMethod:2
- staticMethod:5
- staticMethod:6
- normalMethod:3
- staticMethod:7
- staticMethod:8
- normalMethod:4
- staticMethod:9
- normalMethod:5
- normalMethod:6
- normalMethod:7
- normalMethod:8
- normalMethod:9
那当我们想让所有这个类下面的对象都同步的时候,也就是让所有这个类下面的对象共用同一把锁的时候,我们如何办呢?
法1:将normalMethod方法也改成static,这样这两个static方法都属于类方法,它们获取到的锁都是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。但这样会影响代码结构和对象的封装性。
修改实例1如下:
- package com.bijian.thread;
- public class SynchronizedTest {
- public static synchronized void staticMethod() throws InterruptedException {
- for (int i = 0; i < 10; i++) {
- Thread.sleep(500);
- System.out.println("staticMethod:" + i);
- }
- }
- public static synchronized void normalMethod() throws InterruptedException {
- for (int i = 0; i < 10; i++) {
- Thread.sleep(1000);
- System.out.println("normalMethod:" + i);
- }
- }
- public static void main(String[] args) {
- Thread thread = new Thread(new Runnable() {
- public void run() {
- try {
- SynchronizedTest.normalMethod();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }, "a");
- Thread thread1 = new Thread(new Runnable() {
- public void run() {
- try {
- SynchronizedTest.staticMethod();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }, "b");
- thread1.start();
- thread.start();
- }
- }
运行结果:
- staticMethod:0
- staticMethod:1
- staticMethod:2
- staticMethod:3
- staticMethod:4
- staticMethod:5
- staticMethod:6
- staticMethod:7
- staticMethod:8
- staticMethod:9
- normalMethod:0
- normalMethod:1
- normalMethod:2
- normalMethod:3
- normalMethod:4
- normalMethod:5
- normalMethod:6
- normalMethod:7
- normalMethod:8
- normalMethod:9
也许有人说:将实例1的staticMethod方法改成的static去掉也能达到目的。确实可以,因为非static方法获取到的锁,就是当前调用这个方法的对象的锁,而实例1只有一个SynchronizedTest实例,如再创建一个实例,则就有问题了。如下所示:
- package com.bijian.thread;
- public class SynchronizedTest {
- public synchronized void staticMethod() throws InterruptedException {
- for (int i = 0; i < 10; i++) {
- Thread.sleep(500);
- System.out.println("staticMethod:" + i);
- }
- }
- public synchronized void normalMethod() throws InterruptedException {
- for (int i = 0; i < 10; i++) {
- Thread.sleep(1000);
- System.out.println("normalMethod:" + i);
- }
- }
- public static void main(String[] args) {
- final SynchronizedTest synchronizedTest = new SynchronizedTest();
- Thread thread = new Thread(new Runnable() {
- public void run() {
- try {
- synchronizedTest.normalMethod();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }, "a");
- //为了验证获取到的锁都是当前调用这个方法的对象所属的类,特另新建一个对象
- final SynchronizedTest synchronizedTest2 = new SynchronizedTest();
- Thread thread1 = new Thread(new Runnable() {
- public void run() {
- try {
- synchronizedTest2.staticMethod();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }, "b");
- thread1.start();
- thread.start();
- }
- }
运行结果:
- staticMethod:0
- staticMethod:1
- normalMethod:0
- staticMethod:2
- staticMethod:3
- normalMethod:1
- staticMethod:4
- staticMethod:5
- normalMethod:2
- staticMethod:6
- normalMethod:3
- staticMethod:7
- staticMethod:8
- normalMethod:4
- staticMethod:9
- normalMethod:5
- normalMethod:6
- normalMethod:7
- normalMethod:8
- normalMethod:9
法2:语句块锁,直接看如下实例:
实例2:
- package com.bijian.thread;
- public class SynchronizedTest {
- public final static Byte[] locks = new Byte[0];
- public static void staticMethod() throws InterruptedException {
- synchronized(locks) {
- for (int i = 0; i < 10; i++) {
- Thread.sleep(500);
- System.out.println("staticMethod:" + i);
- }
- }
- }
- public void normalMethod() throws InterruptedException {
- synchronized(locks) {
- for (int i = 0; i < 10; i++) {
- Thread.sleep(1000);
- System.out.println("normalMethod:" + i);
- }
- }
- }
- public static void main(String[] args) {
- final SynchronizedTest synchronizedTest = new SynchronizedTest();
- Thread thread = new Thread(new Runnable() {
- public void run() {
- try {
- synchronizedTest.normalMethod();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }, "a");
- Thread thread1 = new Thread(new Runnable() {
- public void run() {
- try {
- SynchronizedTest.staticMethod();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }, "b");
- thread1.start();
- thread.start();
- }
- }
运行结果:
- staticMethod:0
- staticMethod:1
- staticMethod:2
- staticMethod:3
- staticMethod:4
- staticMethod:5
- staticMethod:6
- staticMethod:7
- staticMethod:8
- staticMethod:9
- normalMethod:0
- normalMethod:1
- normalMethod:2
- normalMethod:3
- normalMethod:4
- normalMethod:5
- normalMethod:6
- normalMethod:7
- normalMethod:8
- normalMethod:9
java中synchronized 用在实例方法和对象方法上面的区别的更多相关文章
- Java中synchronized用在静态方法和非静态方法上面的区别
synchronized 修饰在 static方法和非static方法的区别 在Java中,synchronized是用来表示同步的,我们可以synchronized来修饰一个方法.也可以sync ...
- Java中synchronized 修饰在static方法和非static方法的区别
[问题描述]关于Java中synchronized 用在实例方法和对象方法上面的区别 [问题分析]大家都知道,在Java中,synchronized 是用来表示同步的,我们可以synchronized ...
- java中synchronized的用法详解
记下来,很重要. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchron ...
- java中synchronized的使用方法与具体解释
Java语言的keyword.当它用来修饰一个方法或者一个代码块的时候,可以保证在同一时刻最多仅仅有一个线程运行该段代码. 一.当两个并发线程訪问同一个对象object中的这个synchronized ...
- Java 中 synchronized的用法详解(四种用法)
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码.本文给大家介绍java中 synchronized的用法,对本文感兴趣的朋友一起看看吧 ...
- java中 synchronized 的使用,确保异步执行某一段代码。
最近看了个有关访问网络url和下载的例子,里面有几个synchronized的地方,系统学习下,以下内容很重要,记下来. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一 ...
- JAVA 中 synchronized 详解
看到一篇关于JAVA中synchronized的用法的详解,觉得不错遂转载之..... 原文地址: http://www.cnblogs.com/GnagWang/archive/2011/02/27 ...
- Java中直接输出一个类的对象
例如 package com.atguigu.java.fanshe; public class Person { String name; private int age; public Strin ...
- java中synchronized关键字分析
今天我们来分析一下java中synchronized关键字.首先来看一段java代码:(本地编译环境为mac,jdk1.8的环境) Demo.java package com.example.spri ...
随机推荐
- 【BZOJ3672】【UOJ#6】【NOI2014】随机数生成器
暴力出奇迹 原题: 2≤N,M≤5000 0≤Q≤50000 0≤a≤300 0≤b,c≤108 0≤x0<d≤108 1≤ui,vi≤N×M 恩首先容易看出来这个棋盘直接模拟搞出来就行了,不用 ...
- stl本子
记事本,不要想到奇怪的地方去 迭代器什么的不会玩quq set: #include<set> set<int> quq; quq.insert(qvq); -- 插入 quq. ...
- 替换元素(replace,replace_if,replace_copy,replace_copy_if)
replace 审阅range中的每个元素,把old_value替换为new_value template <class ForwardIterator,class T> void rep ...
- 我发起了一个 用 物理服务器 和 .Net 平台 构建云平台 的 .Net 开源项目
大家好 , 我发起了一个 用 物理服务器 和 .Net 平台 构建云平台 的 .Net 开源项目 . 对 , 用 物理服务器 和 .Net 平台 构建 云平台 . 通过 .Net 构建 分布式 计算集 ...
- JQury基础(一)样式篇
1 初识jQury 1.1 环境搭建 jQuery是一个JavaScript脚本库,不需要特别的安装,只需要我们在页面 标签内中,通过 script 标签引入 jQuery 库即可. <head ...
- tomcat源码阅读之默认连接器
默认连接器 一.UML图: 1.所有的连接器都要实现Connector接口,必须创建Request对象和Response对象,httpConnector作为默认连接器,肯定也是要实现Connector ...
- mysql之 sysbench0.4.12数据库性能测试
1. 常用选项 在Shell中运行以下命令便可得到sysbench的常用选项信息: sysbench --help 上述命令的输出信息如下图所示: 1.1 使用语法 使用sysbench时,可以通过以 ...
- AIX系统日志
1.系统错误日志 存放路径:/var/adm/ras/errlog 说明:该日志记录了系统所检测到的软硬件故障和错误,尤其对系统的硬件故障有很大的参考价值,是AIX提供的最有价值的日志之一, errl ...
- MySQL触发器详解
MySQL触发器 触发器是特殊的存储过程.不同的是,触发器不需要手动调用.只要当预定义的事件发生时,会被MySQL自动调用.主要用于满足复杂业务的规则和需求. 一.创建触发器 1.创建只有一个执行语句 ...
- ML平台_PAI参考
阿里云机器学习PAI(Platform of Artificial Intelligence)是一款一站式的机器学习平台,包含数据预处理.特征工程.常规机器学习算法.深度学习框架.模型的评估以及预测这 ...