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)同步代码块的访问将被阻塞。

时间: 2024-10-11 07:49:00

Java的synchronized的同步代码块和同步方法的区别的相关文章

java 同步代码块与同步方法

同步代码块 synchronized (obj) { // 代码块 } obj 为同步监视器,以上代码的含义为:线程开始执行同步代码块(中的代码)之前,必须先获得对同步监视器的锁定. 代码块中的代码是执行代码,即是某个方法中的某一部分代码,synchronized(obj){}只能出现在某个方法中.如: public void test() { synchronized (obj) { // 代码块 } } 而不能出现在其他位置,如下则报错: public class Test { public

同步监视器之同步代码块、同步方法

如果有多个线程访问共享资源,可能会出现当一个线程没有处理完业务,然后另一个线程进入,从而导致共享资源出现不安全的情况. 日常例子:银行取钱,A和B有拥有同一个银行账户,A用存折在柜台取钱,B在取款机取钱.取钱有两个关键步骤: (1)判断账户里的钱的余额是否大于所取钱数 (2)如果大于所取钱数,则账户最终所剩余额 = 余额 - 所取钱数. 如果没有线程同步的情况下,我们假设这一种情况,这个共同的账户里共1000元. (1)A  B同时去取600元,A所在线程执行到上面的第一个步骤,判断所取钱数小于

2016/9/25编写java实验报告时对synchronized(同步代码块)的一些感悟

通过此次实验,明白了多线程的设置和启动.synchronized代码块的用法.线程的优先级使用方法.知道了那几类资源是线程共享的. 我现在理解的多线程是:实例化一个继承了Thread类或实现了Runnable接口的类(继承是为了使其拥有参与多线程的资格):然后再将该类run()中的代码交由Thread类来执行,以此实现多线程的同步运行 经过翻阅网络博客,和代码尝试,进一步的认识了同步代码块: ①synchronized(){}代码块在执行时先判断括号里的对象有没有被上锁: 若无,则上锁并开始执行

Java线程安全与同步代码块

因为在电商网站工作的原因,对于秒杀.闪购等促销形式相当熟悉.无外乎商家拿出一定量的库存去做所谓的"亏本买卖",其目的是用有限的库存去吸引无限的流量.然而,我却碰到过因为系统问题,导致秒杀品超卖的情况.可怜的商户其实只提供了10双9.9元的童鞋做秒杀,却在瞬间内卖出了1000双! 类似这样的问题,在非线程安全的程序设计中十分常见,我们下面运行一个秒杀的程序: public class SalesThread implements Runnable { private int stock

[java多线程] - 锁机制&同步代码块&信号量

在美眉图片下载demo中,我们可以看到多个线程在公用一些变量,这个时候难免会发生冲突.冲突并不可怕,可怕的是当多线程的情况下,你没法控制冲突.按照我的理解在java中实现同步的方式分为三种,分别是:同步代码块机制,锁机制,信号量机制. 一.同步代码块 在java的多线程并发开发过程中,我们最常用的方式就是使用同步代码关键字(synchronized).这种方式的使用不是特别复杂,需要注意的只是你需要明确到底同步的是那个对象,只有当同步的对象一致的情况下,才能够控制互斥的操作.一般情况下,我们会同

2.2.3用同步代码块解决同步方法的弊端

更改2.2.1代码重新测试 package com.cky.utils; /** * Created by chenkaiyang on 2017/12/6. */ public class Task { private String getData1; private String getData2; public void doLongTimeTask() { try { System.out.println("begin task"); Thread.sleep(3000); S

同步代码块、同步方法以及同步锁的语法

1.同步代码块 在Thread子类run()方法代码块之外套一个下面的代码 synchronized(obj) { ... //此处就是原有的run()方法代码块 } 这里的obj就是需要锁定的对象. 2.同步方法 只要在可变类中修改方法上,加上syschronized修饰即可. 注:同步方法的同步监视器是this. 3.同步锁 先在类中定义锁对象,然后在需要保证线程安全的方法中加锁(锁变量.lock()),最后再在finally块中保证释放锁(锁变量.unlock()) class abc{

写2个线程,一个打印1-52,一个打印A-Z,打印顺序是12A34B。。。(采用同步代码块和同步方法两种同步方法)

1.同步方法 package Synchronized; /************************************同步方法****************************************/ public class PrintTest { public static void main(String[] args) { Print p = new Print(); Thread t1 = new PrintNumber(p); Thread t2 = new P

java:synchronized 同步代码块

synchronized:利用上锁实现数据同步,避免多线程操作的情况下,数据出现异常. 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行. 另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块. 在代码块前加上 synchronized关键字,则此代码块就成为同步代码块, 格式: synchronized(同步对象){ 需要同步的代码: } class MyThread implements Runnab