Java的synchronized的同步代码块和同步方法的区别

本文深入探讨Java中线程同步的两种主要方式:synchronized方法与同步代码块。通过具体示例,解析它们如何作用于同一对象上的锁机制,以及它们在性能和范围上的差异。

线程同步问题大都使用synchronized解决,有同步代码块和同步方法的两种方式,主要记一下这两种的区别

测试代码:

复制代码

 1 package com.xujingyang.testThread;
 2 
 3 public class SynObj{
 4     public synchronized void showA(){
 5         System.out.println("showA..");
 6         try {
 7             Thread.sleep(3000);
 8         } catch (InterruptedException e) {
 9             e.printStackTrace();
10         }
11     }
12     
13     public void showB(){
14         synchronized (this) {
15             System.out.println("showB..");
16         }
17     }
18     
19     public void showC(){
20         String s="1";
21         synchronized (s) {
22             System.out.println("showC..");
23         }
24     }
25 }

复制代码

复制代码

package com.xujingyang.testThread;

public class Test {
    public static void main(String[] args) {
        final SynObj sy=new SynObj();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                sy.showA();
            }
        }).start();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                sy.showB();
            }
        }).start();
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                sy.showC();
            }
        }).start();
    }
}

复制代码

运行结果如下:

 

这段代码的打印结果是,showA…..showC…..会很快打印出来,showB…..会隔一段时间才打印出来,那么showB为什么不能像showC那样很快被调用呢?

  在启动线程1调用方法A后,接着会让线程1休眠3秒钟,这时会调用方法C,注意到方法C这里用synchronized进行加锁,这里锁的对象是s这个字符串对象。但是方法B则不同,是用当前对象this进行加锁,注意到方法A直接在方法上加synchronized,这个加锁的对象是什么呢?显然,这两个方法用的是一把锁。

  *由这样的结果,我们就知道这样同步方法是用什么加锁的了,由于线程1在休眠,这时锁还没释放,导致线程2只有在3秒之后才能调用方法B,由此,可知两种加锁机制用的是同一个锁对象,即当前对象。 
  另外,同步方法直接在方法上加synchronized实现加锁,同步代码块则在方法内部加锁,很明显,同步方法锁的范围比较大,而同步代码块范围要小点,一般同步的范围越大,性能就越差,一般需要加锁进行同步的时候,肯定是范围越小越好,这样性能更好*。

 

 

-----------------------------------------------------------------------------------------------------------------------------------------------

     一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。 
     二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。 
     三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

==========================================================================================================       曾经的理想是做个程序员,那时以为程序就是计算机的全部。现在依然喜欢程序,但是开始明白,程序并不是计算机的全部,好的程序,好的程序员要经历漫长的修炼,就像是武林高手修炼内功比招式更重要。我要做的是程序员,不是coder。 
       请记住:你比他好一点,他不会承认你,反而会嫉妒你,只有你比他好很多,他才会承认你,然后还会很崇拜你,所以要做,就一定要比别人做得好很多!

http://www.cnblogs.com/xujingyang/p/6565606.html

Java 同步代码块同步方法存在多方面的区别: - **锁对象**:同步方法中,实例方法默认锁住当前对象(`this`),静态方法锁住类的 `Class` 对象(如 `ClassName.class`);而同步代码块需显式指定锁对象,该对象可以是任意对象,灵活性更高。例如: ```java public class Example { // 同步实例方法,锁对象是当前实例 public synchronized void syncMethod() { // 方法内容 } // 静态同步方法,锁对象是 Example.class public static synchronized void staticSyncMethod() { // 方法内容 } private final Object lock = new Object(); public void syncBlock() { // 同步代码块,锁对象是 lock synchronized (lock) { // 同步代码 } } } ``` - **控制粒度**:同步方法会锁定整个方法体,当方法体较大时,可能导致性能问题;同步代码块仅锁定必要的代码段,能够减少锁的持有时间,从而提高并发效率。例如,若一个方法中只有部分代码需要同步,使用同步代码块更为合适 [^1][^2]。 ```java public class Counter { private int count = 0; // 同步方法,整个方法同步 public synchronized void incrementMethod() { // 一些不需要同步的操作 // ... count++; // 一些不需要同步的操作 // ... } // 同步代码块,仅对关键部分同步 public void incrementBlock() { // 一些不需要同步的操作 // ... synchronized (this) { count++; } // 一些不需要同步的操作 // ... } } ``` - **灵活性**:同步代码块可以针对不同的资源使用独立的锁对象,从而降低线程之间的竞争;而同步方法受限于隐式的锁对象,灵活性较差 [^2]。 综上所述,同步方法简单但不够灵活,适合整个方法都需要同步的场景;同步代码块更灵活、性能更高,适合需要细粒度控制的场景。核心原则是锁的粒度越小,并发性能越高 [^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值