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 ...
随机推荐
- html2canvas用法的总结(转载)
最近做h5网页,有个功能是用户能长按页面保存为图片,在我们理解就是网页要生成图片然后再让用户长按保存,然后就发现了html2canvas这个框架了,效果挺不错了,但是有几个坑说一下(用的最新版): h ...
- struts2 中的数据访问servletAPI
ActionContext包含其他数据对象,包括值栈 每次请求都会创建一个ActionContext对象 通过ActionContext访问数据 在action中读取 在jsp页面中读取 1 ...
- DevExpress Cpicturebox或者Dev控件 PictureEdit 按比例的缩放加载图片
方法一: 如果要加载的图片的长宽比不是太过失衡, 1.可以改变picturebox的SizeMode属性为 PictureBoxSizeMode.StretchImage, 2.或者Dev控件 ...
- [转]分布式系统唯一ID生成方案汇总
系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,也常常为这个问题而纠结.生成ID的方法有很多,适应不同的场景.需求以及性能要求.所以有些比较复杂的系统会有多个ID生成的策略.下面就介绍一些常见 ...
- node 各模块及对应功能
node 各模块及对应功能 node 模块 对应功能 net 处理 TCP dgram 处理 UDP http 处理 HTTP/1 http2 处理 HTTP/2 https 处理 HTTPS tls ...
- ts项目报错:Import sources within a group must be alphabetized
报错:Import sources within a group must be alphabetized. 原因:import名称排序问题,要求按照字母从小到大排序:修改 tslint.json 中 ...
- laravel 获取上一条insert语句产生的id
<?php //頭部引入DB類 use Illuminate\Support\Facades\DB; //在方法中獲取获取上一条insert语句产生的id $id = DB::getPdo()- ...
- PyCharm 链接MySQL 数据库
1.View -> Tool Windows-Database; 2.添加数据源: 3.配置数据库的驱动信息: 4.设置驱动文件,勾选“Use Provided driver MySQL Con ...
- RedHat7局域网下安装离线Ambari
1 Ambari介绍.安装与应用案例介绍 1.1 Ambari Ambari 跟 Hadoop 等开源软件一样,也是 Apache Software Foundation 中的一个项目,并且是顶级项目 ...
- mongodb morphia删除数组中指定条件的数据
先看mongodb操作: db.test.update({"msgid":170},{"$pull":{"msg":{"comti ...