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 ...
随机推荐
- dup等复制文件描述符函数
[root@bogon code]# cat b.c #include<stdio.h> #include<error.h> #include<unistd.h> ...
- C# Winform 怎么让按钮在Panel里居中显示
把pannel里面的多个按钮的那个anchor属性全部去掉,如下图: 再用VS2010自带的工具调一下即可: 小注: 有的时候我们却想子控件在父控件里的相对位置不要随着父控件的变大缩小而变化,或者控件 ...
- ES5新增数组方法
forEach/map every/some indexOf/lastIndexOf filter reduce Array.isArray
- tomcat源码阅读之BackupManager
一. 配置: <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOpti ...
- zookeeper 学习资料
zookeeper 学习资料 学习资料 网址 Zookeeper 教程(菜鸟教程) https://www.w3cschool.cn/zookeeper/
- 数学集合:N Z Q R C
整数: Zahlen(德) 复数: Complex number 实数: Real number 自然数: Natural number 有理数: Quotient(德,"商&quo ...
- Linux下C与Mysql的混合编程(转)
1 概述 MySQL 是一个关系型数据库管理系统.由瑞典MySQL AB公司开发,眼下属于Oracle公司.MySQL是最流行的关系型数据库管理系统. 支持AIX.FreeBSD.HP-UX.Linu ...
- java byte数组与String的相互转换
String -> byte数组 String str = "abc天"; byte[] btr = str.getBytes(); System.out.printl ...
- ASP.NET中JSON的序列化和反序列化(转)
JSON是专门为浏览器中的网页上运行的JavaScript代码而设计的一种数据格式.在网站应用中使用JSON的场景越来越多,本文介绍ASP.NET中JSON的序列化和反序列化,主要对JSON的简单介绍 ...
- 浅析Hyperledger Fabric共识算法 摘自http://www.cocoachina.com/blockchain/20180829/24728.html
Hyperledger Fabric共识算法 区块链系统是一个分布式架构,交易账本信息由各个节点管理,组成一个庞大的分布式账本.在分布式系统中,各个节点收到的交易信息的顺序可能存在差异(例如,网络延迟 ...