初始化一个对象时,会自动生成一个与该对象对应的对象锁,被synchronized 修饰的方法就得依靠对象锁工作。当多线程同时访问某个被synchronized修饰的方法时,一旦某个进程抢得对象锁之后,其他的进程只有排队对待。

一、synchronized修饰普通方法

初始化一个对象时,会自动生成一个与该对象对应的对象锁,被synchronized 修饰的方法就得依靠对象锁工作。当多线程同时访问某个被synchronized修饰的方法时,一旦某个进程抢得对象锁之后,其他的进程只有排队对待。

例如,Person类里有2个被synchronized 修饰的方法,…还是看代码吧:

public  class Person {public synchronized void eatApple() {Log.d("TAG", "eatApple begin at:" + System.currentTimeMillis());SystemClock.sleep(3000);Log.d("TAG", "eatApple end at:" + System.currentTimeMillis());}public synchronized void eatOrange() {for (int i = 0; i < 10; i++) {Log.d("TAG", "eatOrange is running");SystemClock.sleep(200);}}
}
public class MainActivity extends AppCompatActivity {Person person = new Person();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);thread1.start();thread2.start();}Thread thread1 = new Thread(new Runnable() {@Overridepublic void run() {person.eatApple();}});Thread thread2 = new Thread(new Runnable() {@Overridepublic void run() {person.eatOrange();}});}

运行结果:

12-14 16:26:48.243 14867-14920/com.example.shengqf.myapplication D/TAG: eatApple begin at:1513240008242
12-14 16:26:51.244 14867-14920/com.example.shengqf.myapplication D/TAG: eatApple end at:1513240011243
12-14 16:26:51.246 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:26:51.447 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:26:51.648 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:26:51.848 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:26:52.049 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:26:52.250 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:26:52.451 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:26:52.652 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:26:52.853 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:26:53.055 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running

结论:因为thread1中的eatApple()方法和thread2中的eatOrange()方法都是通过person对象调用的,他们用的是同一个对象锁,互斥。所以,thread2一直等到thread1中的eatApple()方法执行完释放了对象锁后才开始执行其eatOrange()方法。

现在将上面thread2代码改一下:

  Thread thread2 = new Thread(new Runnable() {@Overridepublic void run() {Person person2 = new Person();person2.eatOrange();}});

再运行,结果:

12-14 16:43:05.011 16294-16320/com.example.shengqf.myapplication D/TAG: eatApple begin at:1513240985011
12-14 16:43:05.011 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:43:05.211 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:43:05.412 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:43:05.612 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:43:05.813 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:43:06.014 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:43:06.215 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:43:06.416 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:43:06.617 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:43:06.818 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-14 16:43:08.012 16294-16320/com.example.shengqf.myapplication D/TAG: eatApple end at:1513240988011

因为thread1中的eatApple()方法是通过person对象调用的,而thread2中的eatOrange()方法是通过person2对象调用的,他们用的是两个不同的对象锁,并不互斥。所以,thread2中的eatOrange()方法是和thread1中的eatApple()方法同时进行的。

结论:使用“同一个对象”去调用其被synchronized 修饰的普通方法才互斥。

上面的Person类等效于:

public class Person{public void eatApple() {synchronized(Person.this){Log.d("TAG", "eatApple begin at:" + System.currentTimeMillis());SystemClock.sleep(3000);Log.d("TAG", "eatApple end at:" + System.currentTimeMillis());}}public void eatOrange() {synchronized (Person.this) {for (int i = 0; i < 10; i++) {Log.d("TAG", "eatOrange is running");SystemClock.sleep(200);}}}
}
二、synchronized修饰静态方法

直接看代码:

public class Person {public synchronized static void eatApple() {Log.d("TAG", "eatApple begin at:" + System.currentTimeMillis());SystemClock.sleep(3000);Log.d("TAG", "eatApple end at:" + System.currentTimeMillis());}public synchronized static void eatOrange() {for (int i = 0; i < 10; i++) {Log.d("TAG", "eatOrange is running");SystemClock.sleep(200);}}
}
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);thread1.start();thread2.start();}Thread thread1 = new Thread(new Runnable() {@Overridepublic void run() {Person.eatApple();}});Thread thread2 = new Thread(new Runnable() {@Overridepublic void run() {Person.eatOrange();}});}

运行结果:

12-15 09:09:24.378 31625-31912/com.example.shengqf.myapplication D/TAG: eatApple begin at:1513300164378
12-15 09:09:27.379 31625-31912/com.example.shengqf.myapplication D/TAG: eatApple end at:1513300167379
12-15 09:09:27.381 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:09:27.582 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:09:27.783 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:09:27.984 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:09:28.184 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:09:28.385 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:09:28.585 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:09:28.786 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:09:28.986 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:09:29.188 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running

现在将thread1和thread2代码改为:

Thread thread1 = new Thread(new Runnable() {@Overridepublic void run() {Person person1 = new Person();person1.eatApple();}});Thread thread2 = new Thread(new Runnable() {@Overridepublic void run() {Person person2 = new Person();person2.eatOrange();}});

再运行结果:

12-15 09:12:38.316 32353-32378/com.example.shengqf.myapplication D/TAG: eatApple begin at:1513300358316
12-15 09:12:41.317 32353-32378/com.example.shengqf.myapplication D/TAG: eatApple end at:1513300361317
12-15 09:12:41.320 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:12:41.521 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:12:41.721 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:12:41.922 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:12:42.123 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:12:42.324 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:12:42.525 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:12:42.727 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:12:42.928 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running
12-15 09:12:43.129 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running

因为eatApple()和eatOrange()方法都是Person类里的静态方法,且被synchronized修饰,所以这两个方法都是靠唯一的Person类锁工作,所以无论是通过Person类名调用还是new不同的person对象调用,两个方法都是互斥的。

结论:被synchronized 修饰的静态方法要靠类锁工作。当多线程同时访问某个被synchronized修饰的静态方法时,一旦某个进程抢得该类的类锁之后,其他的进程只有排队对待。

上面的Person代码等效于:

public class Person {public static void eatApple() {synchronized(Person.class){Log.d("TAG", "eatApple begin at:" + System.currentTimeMillis());SystemClock.sleep(3000);Log.d("TAG", "eatApple end at:" + System.currentTimeMillis());}}public static void eatOrange() {synchronized(Person.class){for (int i = 0; i < 10; i++) {Log.d("TAG", "eatOrange is running");SystemClock.sleep(200);}}}
}

Java多线程--synchronized修饰普通方法和修饰静态方法的区别相关推荐

  1. java多线程中的join方法详解

    java多线程中的join方法详解 方法Join是干啥用的? 简单回答,同步,如何同步? 怎么实现的? 下面将逐个回答. 自从接触Java多线程,一直对Join理解不了.JDK是这样说的:join p ...

  2. Java多线程-synchronized关键字

    进程:是一个正在执行中的程序.每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控制单元. 线程:就是进程中的一个独立的控制单元.线程在控制着进程的执行. 一个进程中至少有一个线程 Ja ...

  3. java多线程同步5种方法

    一.引言 前几天面试,被大师虐残了,好多基础知识必须得重新拿起来啊.闲话不多说,进入正题. 二.为什么要线程同步 因为当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会 ...

  4. JAVA多线程基础篇-join方法的使用

    1.概述 join()是Thread类中的一个方法,它的作用是将当前线程挂起,等待其他线程结束后再执行当前线程,即当前线程等待另一个调用join()方法的线程执行结束后再往下执行.通常用于在main主 ...

  5. Java多线程wait()和notify()方法图解

    多线程wait()和notify()方法详解 文章目录 多线程wait()和notify()方法详解 前言 一.线程间等待与唤醒机制 二.等待方法wait() 三.唤醒方法notify() 四.关于w ...

  6. Java多线程问题--schedule函数和scheduleAtFixedRate的用法和区别

    本文内容部分引自<Java多线程编程核心技术>,感谢作者!!! 代码地址:https://github.com/xianzhixianzhixian/thread.git schedule ...

  7. java多线程synchronized底层实现

    一直想把这个特别重要的关键词的底层实现搞明白.(当然现在也没有完全明白,如果有错误以后修改这篇文章) 首先,这个关键词synchronize可以说是个语法糖,它的具体用法网上很多博客都讲的比较明了了. ...

  8. Java多线程:在run方法中每隔一百毫秒打印一句话

    package com.company;/*** 尝试定义一个继承Thread类的类,并覆盖run方法,在run方法中每隔一百毫秒打印一句话*/ public class Usecase3 exten ...

  9. java 多线程 submit future.get方法阻塞问题的解决,实现按照任务完成的先后顺序获取任务的结果

    1.Future Future模式是多线程设计常用的一种设计模式.Future模式可以理解成:我有一个任务,提交给了Future,Future替我完成这个任务.期间我自己可以去做任何想做的事情.一段时 ...

最新文章

  1. Ubuntu下安装Cppcheck源码操作步骤
  2. 取input 输入_tensorRT动态输入(python)
  3. pmp考试中容易混淆的22组概念
  4. CSS3黑色大气绘图着陆页模板
  5. 深入理解PHP之数组(遍历顺序)
  6. IntelliJ IDEA 文件夹重命名--解决重命名后js文件引用找不到路径报404错误
  7. 关于微信小程序中uView中通过packer选择器修改表单无法触发form组件的表单验证的问题
  8. Spring Cloud 和 Dubbo,到底用哪个好?
  9. 工作中不要扯虎皮吓唬人
  10. 问题解决逻辑:深度和广度谁应该优先?
  11. mysql 99乘法表_MySQL 通过sql输出99乘法表
  12. beego框架:static目录下的apk文件浏览器下载使用正常,手机浏览器下载无法解析安装
  13. iOS项目添加pch文件
  14. 巨帧(jumbo frame)
  15. python jit_Pypy Python的JIT实现
  16. 华米手表会安装鸿蒙系统那,【教程】华米运动手表3安装第三方应用、第三方表盘及使用教程...
  17. 哈佛大学凌晨4点半的景象 .
  18. 婚恋交友app源码,搭建一个流媒体服务
  19. idea关闭所有打开的项目窗口
  20. 初探技术管理(3)-团队建设

热门文章

  1. 为什么销量总是做不好预测?或许你只差这一份强化资料包
  2. 太赞了!《Python知识手册》更新到v2.2版
  3. 【机器学习基础】八种应对样本不均衡的策略
  4. 矩阵求导术(上、下)
  5. 统计学习方法第七章作业:SVM非线性支持向量机之SMO序列最小优化算法代码实现
  6. 推荐算法炼丹笔记:推荐系统采样评估指标及线上线下一致性问题
  7. 亮相 LiveVideoStackCon 2021,网易云信解构自研大规模传输网 WE-CAN
  8. 以效率为根本,网易慢跑要做“另类”的TO B业务
  9. SQL存在一个表而不在还有一个表中的数据
  10. Exchange数据保护