https://bijian1013.iteye.com/blog/1836575

在Java中,synchronized 是用来表示同步的,我们可以synchronized 来修饰一个方法。也可以synchronized 来修饰方法里面的一个语句块。

修饰实例方法:

  1. public synchronized void normalMethod() throws InterruptedException {
  2. for (int i = 0; i < 10; i++) {
  3. Thread.sleep(1000);
  4. System.out.println("normalMethod:" + i);
  5. }
  6. }

修饰类方法(static 方法):

  1. public static synchronized void staticMethod() throws InterruptedException {
  2. for (int i = 0; i < 10; i++) {
  3. Thread.sleep(500);
  4. System.out.println("staticMethod:" + i);
  5. }
  6. }

修饰方法里面语句块:

  1. public static void staticMethod() throws InterruptedException  {
  2. synchronized (locks) {
  3. for (int i = 0; i < 10; i++)  {
  4. Thread.sleep(1000);
  5. System.out.println("staticMethod:" + i);
  6. }
  7. }
  8. }

注意:这里不能用synchronized修饰方法外面的语句块(我把他叫做类语句块),虽然我们可以在方法外面定义语句块,这样做会遇到编译错误,这里涉及到了Java里面的对象初始化的部分知识。大概的原因就是synchronized锁住的是对象,当初始化对象的时候,JVM在对象初始化完成之前会调用方法外面的语句块,这个时候对象还不存在,所以就不存在锁了。

那么,在static方法和非static方法前面加synchronized到底有什么不同呢?

static的方法属于类方法,它属于这个Class(注意:这里的Class不是指Class的某个具体对象),那么static获取到的锁,就是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。而非static方法获取到的锁,就是当前调用这个方法的对象的锁了。所以,他们之间不会产生互斥。

实例1:

  1. package com.bijian.thread;
  2. public class SynchronizedTest {
  3. public static synchronized void staticMethod() throws InterruptedException {
  4. for (int i = 0; i < 10; i++) {
  5. Thread.sleep(500);
  6. System.out.println("staticMethod:" + i);
  7. }
  8. }
  9. public synchronized void normalMethod() throws InterruptedException {
  10. for (int i = 0; i < 10; i++) {
  11. Thread.sleep(1000);
  12. System.out.println("normalMethod:" + i);
  13. }
  14. }
  15. public static void main(String[] args) {
  16. final SynchronizedTest synchronizedTest = new SynchronizedTest();
  17. Thread thread = new Thread(new Runnable() {
  18. public void run() {
  19. try {
  20. synchronizedTest.normalMethod();
  21. } catch (InterruptedException e) {
  22. e.printStackTrace();
  23. }
  24. }
  25. }, "a");
  26. Thread thread1 = new Thread(new Runnable() {
  27. public void run() {
  28. try {
  29. SynchronizedTest.staticMethod();
  30. } catch (InterruptedException e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. }, "b");
  35. thread1.start();
  36. thread.start();
  37. }
  38. }

运行结果:

  1. staticMethod:0
  2. normalMethod:0
  3. staticMethod:1
  4. staticMethod:2
  5. normalMethod:1
  6. staticMethod:3
  7. staticMethod:4
  8. normalMethod:2
  9. staticMethod:5
  10. staticMethod:6
  11. normalMethod:3
  12. staticMethod:7
  13. staticMethod:8
  14. normalMethod:4
  15. staticMethod:9
  16. normalMethod:5
  17. normalMethod:6
  18. normalMethod:7
  19. normalMethod:8
  20. normalMethod:9

那当我们想让所有这个类下面的对象都同步的时候,也就是让所有这个类下面的对象共用同一把锁的时候,我们如何办呢?

法1:将normalMethod方法也改成static,这样这两个static方法都属于类方法,它们获取到的锁都是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。但这样会影响代码结构和对象的封装性。

修改实例1如下:

  1. package com.bijian.thread;
  2. public class SynchronizedTest {
  3. public static synchronized void staticMethod() throws InterruptedException {
  4. for (int i = 0; i < 10; i++) {
  5. Thread.sleep(500);
  6. System.out.println("staticMethod:" + i);
  7. }
  8. }
  9. public static synchronized void normalMethod() throws InterruptedException {
  10. for (int i = 0; i < 10; i++) {
  11. Thread.sleep(1000);
  12. System.out.println("normalMethod:" + i);
  13. }
  14. }
  15. public static void main(String[] args) {
  16. Thread thread = new Thread(new Runnable() {
  17. public void run() {
  18. try {
  19. SynchronizedTest.normalMethod();
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. }, "a");
  25. Thread thread1 = new Thread(new Runnable() {
  26. public void run() {
  27. try {
  28. SynchronizedTest.staticMethod();
  29. } catch (InterruptedException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. }, "b");
  34. thread1.start();
  35. thread.start();
  36. }
  37. }

运行结果:

  1. staticMethod:0
  2. staticMethod:1
  3. staticMethod:2
  4. staticMethod:3
  5. staticMethod:4
  6. staticMethod:5
  7. staticMethod:6
  8. staticMethod:7
  9. staticMethod:8
  10. staticMethod:9
  11. normalMethod:0
  12. normalMethod:1
  13. normalMethod:2
  14. normalMethod:3
  15. normalMethod:4
  16. normalMethod:5
  17. normalMethod:6
  18. normalMethod:7
  19. normalMethod:8
  20. normalMethod:9

也许有人说:将实例1的staticMethod方法改成的static去掉也能达到目的。确实可以,因为非static方法获取到的锁,就是当前调用这个方法的对象的锁,而实例1只有一个SynchronizedTest实例,如再创建一个实例,则就有问题了。如下所示:

  1. package com.bijian.thread;
  2. public class SynchronizedTest {
  3. public synchronized void staticMethod() throws InterruptedException {
  4. for (int i = 0; i < 10; i++) {
  5. Thread.sleep(500);
  6. System.out.println("staticMethod:" + i);
  7. }
  8. }
  9. public synchronized void normalMethod() throws InterruptedException {
  10. for (int i = 0; i < 10; i++) {
  11. Thread.sleep(1000);
  12. System.out.println("normalMethod:" + i);
  13. }
  14. }
  15. public static void main(String[] args) {
  16. final SynchronizedTest synchronizedTest = new SynchronizedTest();
  17. Thread thread = new Thread(new Runnable() {
  18. public void run() {
  19. try {
  20. synchronizedTest.normalMethod();
  21. } catch (InterruptedException e) {
  22. e.printStackTrace();
  23. }
  24. }
  25. }, "a");
  26. //为了验证获取到的锁都是当前调用这个方法的对象所属的类,特另新建一个对象
  27. final SynchronizedTest synchronizedTest2 = new SynchronizedTest();
  28. Thread thread1 = new Thread(new Runnable() {
  29. public void run() {
  30. try {
  31. synchronizedTest2.staticMethod();
  32. } catch (InterruptedException e) {
  33. e.printStackTrace();
  34. }
  35. }
  36. }, "b");
  37. thread1.start();
  38. thread.start();
  39. }
  40. }

运行结果:

  1. staticMethod:0
  2. staticMethod:1
  3. normalMethod:0
  4. staticMethod:2
  5. staticMethod:3
  6. normalMethod:1
  7. staticMethod:4
  8. staticMethod:5
  9. normalMethod:2
  10. staticMethod:6
  11. normalMethod:3
  12. staticMethod:7
  13. staticMethod:8
  14. normalMethod:4
  15. staticMethod:9
  16. normalMethod:5
  17. normalMethod:6
  18. normalMethod:7
  19. normalMethod:8
  20. normalMethod:9

 法2:语句块锁,直接看如下实例:

实例2:

  1. package com.bijian.thread;
  2. public class SynchronizedTest {
  3. public final static Byte[] locks = new Byte[0];
  4. public static void staticMethod() throws InterruptedException {
  5. synchronized(locks) {
  6. for (int i = 0; i < 10; i++) {
  7. Thread.sleep(500);
  8. System.out.println("staticMethod:" + i);
  9. }
  10. }
  11. }
  12. public void normalMethod() throws InterruptedException {
  13. synchronized(locks) {
  14. for (int i = 0; i < 10; i++) {
  15. Thread.sleep(1000);
  16. System.out.println("normalMethod:" + i);
  17. }
  18. }
  19. }
  20. public static void main(String[] args) {
  21. final SynchronizedTest synchronizedTest = new SynchronizedTest();
  22. Thread thread = new Thread(new Runnable() {
  23. public void run() {
  24. try {
  25. synchronizedTest.normalMethod();
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }, "a");
  31. Thread thread1 = new Thread(new Runnable() {
  32. public void run() {
  33. try {
  34. SynchronizedTest.staticMethod();
  35. } catch (InterruptedException e) {
  36. e.printStackTrace();
  37. }
  38. }
  39. }, "b");
  40. thread1.start();
  41. thread.start();
  42. }
  43. }

运行结果:

  1. staticMethod:0
  2. staticMethod:1
  3. staticMethod:2
  4. staticMethod:3
  5. staticMethod:4
  6. staticMethod:5
  7. staticMethod:6
  8. staticMethod:7
  9. staticMethod:8
  10. staticMethod:9
  11. normalMethod:0
  12. normalMethod:1
  13. normalMethod:2
  14. normalMethod:3
  15. normalMethod:4
  16. normalMethod:5
  17. normalMethod:6
  18. normalMethod:7
  19. normalMethod:8
  20. normalMethod:9

java中synchronized 用在实例方法和对象方法上面的区别的更多相关文章

  1. Java中synchronized用在静态方法和非静态方法上面的区别

    synchronized 修饰在 static方法和非static方法的区别   在Java中,synchronized是用来表示同步的,我们可以synchronized来修饰一个方法.也可以sync ...

  2. Java中synchronized 修饰在static方法和非static方法的区别

    [问题描述]关于Java中synchronized 用在实例方法和对象方法上面的区别 [问题分析]大家都知道,在Java中,synchronized 是用来表示同步的,我们可以synchronized ...

  3. java中synchronized的用法详解

    记下来,很重要. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchron ...

  4. java中synchronized的使用方法与具体解释

    Java语言的keyword.当它用来修饰一个方法或者一个代码块的时候,可以保证在同一时刻最多仅仅有一个线程运行该段代码. 一.当两个并发线程訪问同一个对象object中的这个synchronized ...

  5. Java 中 synchronized的用法详解(四种用法)

    Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码.本文给大家介绍java中 synchronized的用法,对本文感兴趣的朋友一起看看吧 ...

  6. java中 synchronized 的使用,确保异步执行某一段代码。

    最近看了个有关访问网络url和下载的例子,里面有几个synchronized的地方,系统学习下,以下内容很重要,记下来. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一 ...

  7. JAVA 中 synchronized 详解

    看到一篇关于JAVA中synchronized的用法的详解,觉得不错遂转载之..... 原文地址: http://www.cnblogs.com/GnagWang/archive/2011/02/27 ...

  8. Java中直接输出一个类的对象

    例如 package com.atguigu.java.fanshe; public class Person { String name; private int age; public Strin ...

  9. java中synchronized关键字分析

    今天我们来分析一下java中synchronized关键字.首先来看一段java代码:(本地编译环境为mac,jdk1.8的环境) Demo.java package com.example.spri ...

随机推荐

  1. golang 内存占用测量

    web服务中加入如下 import ( "runtime" "time" "fmt" ) go func() { for { var m r ...

  2. linux ssh的安装与配置以及实现密钥登录

    安装ssh服务器: yum install openssh ssh 配置文件位于/etc/ssh/sshd_config 如果需要允许root用户远程登录,那么vi /etc/ssh/sshd_con ...

  3. day43 数据库学习egon的博客 索引

    一 介绍 为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句 ...

  4. AI三巨头获2018年图灵奖!

    ACM 宣布,2018 年图灵奖获得者是号称深度学习三巨头的 Yoshua Bengio, Yann LeCun 和 Geoffrey Hinton,得奖理由是:他们在概念和工程上取得的巨大突破,使得 ...

  5. 标 题: JavaScript真的要一统江湖了

    http://www.newsmth.net/nForum/#!article/Python/125347?p=4 标  题: JavaScript真的要一统江湖了 发信站: 水木社区 (Fri Se ...

  6. webpack 4 学习资料

    webpack 4 学习资料 资料 网址 webpack 中文版 https://webpack.docschina.org/configuration/ webpack 4 教程 https://s ...

  7. dockerfile创建php容器(安装memcached、redis、gd、xdebug扩展)

    dockerfile创建php容器(含有memcached.redis.gd.xdebug扩展) 代码如下: FROM php:7.2-fpm COPY redis-3.1.6.tgz /home/r ...

  8. ASP.NET AJAX入门系列(2):使用ScriptManager控件

    ScriptManager控件包括在ASP.NET 2.0 AJAX Extensions中,它用来处理页面上的所有组件以及页面局部更新,生成相关的客户端代理脚本以便能够在JavaScript中访问W ...

  9. 配置Hanlp自然语言处理进阶

    中文分词 中文分词中有众多分词工具,如结巴.hanlp.盘古分词器.庖丁解牛分词等:其中庖丁解牛分词仅仅支持java,分词是HanLP最基础的功能,HanLP实现了许多种分词算法,每个分词器都支持特定 ...

  10. mysql程序之mysqladmin详解

    mysqladmin命令 mysqladmin是执行管理操作的客户端.您可以使用它来检查服务器的配置和当前状态,以创建和删除数据库等 用法: mysqladmin [OPTIONS] command ...