深入理解使用synchronized同步方法和同步代码块的区别

一.代码块和方法之间的区别

首先需要知道代码块和方法有什么区别:

构造器和方法块,构造器可以重载也就是说明在创建对象时可以按照不同的构造器来创建,那么构造器是属于对象,而代码块呢他是给所有的对象初始化的。底下看一个列子:

public class Constructor_Methodblock {
    private int num;
    private String str;
    //构造器
    public Constructor_Methodblock(int num,String str){
        System.out.println("\n************构造器****************");
        System.out.println("在进入构造器之前成员变量的值为num:"+this.num+"str: "+this.str);
        this.str=str;
        this.num=num;
        System.out.println("赋值之后num为"+num+"str为"+str);
    }
    //方法块
    {
        System.out.println("\n************代码块****************");
        System.out.println("在进入方法块之前成员变量的值为num:"+num+"str: "+str);
        num=1;
        str="li";
        System.out.println("赋值之后num为"+num+"str为"+str);
    }

    public static void main(String[] args) {
        new Constructor_Methodblock(2,"fei");
    }
}

结果为:

发现代码块比构造器早执行,而且代码块是所有的对象都要执行的。

现在我们对代码块和方法有了一定的了解,那么同步方法有什么缺点使得我们需要同步代码块呢?

二.同步方法的缺点

来想象一个这样的情况:一个方法其中有一部分是需要计算数据花费时间不是那么长但是还有一部分他不需要处理数据但是他需要花费大量的时间,那么如果我们直接将这个方法同步化会导致整体的代码性能下降,而我们仅仅将这个计算数据部分同步保证共享数据计算没有问题,那么代码性能是不是就上去了呢?

来看直接同步化方法:

public class SynFun extends Thread {
    private int num=10;//共享数据
    @Override
     public void run(){
        try {
            this.fun();//调用同步方法
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void fun() throws InterruptedException {
        //使用睡眠来模拟一下复杂但是对数据处理没有关系的部分,睡眠三秒
        Thread.sleep(3000);
                System.out.println("修改前的num为"+num);
                num--;
                System.out.println("修改后的num为"+num);
        System.out.println("*************");
    }

    public static void main(String[] args) {

        SynFun synFun=new SynFun();
        Thread t1=new Thread(synFun);
        Thread t2=new Thread(synFun);
        t1.start();
        t2.start();

    }
}

结果为:出现结果时,先等待了三秒出现了第一个结果,在等待了三秒又出现了第二个结果。

改进一下:

public  void fun() throws InterruptedException {
        //使用睡眠来模拟一下复杂但是对数据处理没有关系的部分,睡眠三秒
        Thread.sleep(3000);
        synchronized (this){
            System.out.println("修改前的num为"+num);
            num--;
            System.out.println("修改后的num为"+num);
        }
        System.out.println("*************");
    }

就是利用同步化代码块,将共享数据处理的部分同步起来,而其他的部分就让他去交叉运行吧。

结果是一样的,但是出现结果就是三秒以后直接出现两个答案,说明整体性能直接上去了。

******************************************************题外话***********************************************************

Java多线程专题已经已经发表了五篇博客了,不少前辈(其实我还是一个大二的学生)都给出了很好的讲解和指导,在这里真的非常感谢你们。

1   if(对我的博客感兴趣){
2         点赞+关注;
3     }else{
4         没有else
5     }

原文地址:https://www.cnblogs.com/SAM-CJM/p/9806787.html

时间: 2024-10-10 17:41:36

深入理解使用synchronized同步方法和同步代码块的区别的相关文章

java的同步方法和同步代码块,对象锁,类锁区别

/** * @author admin * @date 2018/1/12 9:48 * 作用在同一个实例对象上讨论 * synchronized同步方法的测试 * 两个线程,一个线程调用synchronized修饰方法,另一个线程可以调用非synchronized修饰的方法,互不影响 */ public class SynchronizedTest { public synchronized void methodA() { try { for (int i = 0; i < 5; i++)

同步方法、同步代码块、volidate变量的使用

当多个线程涉及到共享数据的时候,就会设计到线程安全的问题.非线程安全其实会在多个线程对同一个对象中的实例变量进行并发访问时发生,产生的后果就是"脏读".发生脏读,就是取到的数据已经被其他的线程改过了.什么是线程安全呢?用并发编程实战里面的一段话解释说: 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的 这里需要注意的是多个线程,如果一个线程肯定是线程安全的,而

同步方法和同步代码块

打个比方:一个object就像一个大房子,大门永远打开.房子里有很多房间(也就是方法).这些房间有上锁的(synchronized方法),和不上锁之分(普通方法).房门口放着一把钥匙(key),这把钥匙可以打开所有上锁的房间.另外我把所有想调用该对象方法的线程比喻成想进入这房子某个房间的人.所有的东西就这么多了,下面我们看看这些东西之间如何作用的. 在此我们先来明确一下我们的前提条件.该对象至少有一个synchronized方法,否则这个key还有啥意义.当然也就不会有我们的这个主题了. 一个人

synchronized 与 ReentrantLock 同步代码块简单实现

synchronized 同步代码块: package net.flyingfat.lock; public class SyncLock { public static void main(String args[]){ final SyncLock lock=new SyncLock(); Thread.currentThread().setName("main"); new Thread(new Runnable() { public void run() { Thread.cu

同步方法和同步代码块的区别是什么?

同步方法默认用this或者当前类class对象作为锁. 同步代码可以选择以什么来加锁,比同步方法更细颗粒化,同步代码可以同步有同步问题的部分代码而不是整个方法. 同步方法用关键字synchronized修饰方法,同步代码主要修饰需要进行同步的代码块,用synchronized(object){代码内容}进行修饰. 原文地址:https://www.cnblogs.com/Freak-Lew/p/9196268.html

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 (InterruptedEx

synchronized同步代码块锁释放

今天发现自己写的线上程序出现数据库不能同步的问题,查看日志已经停止记录,随后使用jstack查看线程的运行状况,发现有个同步线程锁住了. 以下是jstack -l 637  问题线程的内容. "schedulerJob-t-291" #314 daemon prio=5 os_prio=0 tid=0x00007f7d64844800 nid=0x3d5 runnable [0x00007f7d3a107000] java.lang.Thread.State: RUNNABLE at

java中的静态代码块、构造代码块、普通代码块和同步代码块总结

java中的4中代码块总结如下: * 加了static的是静态代码块,在类中写了一对{}是构造代码块,在方法中写了一对{}是普通代码块, * java中还有一种代码块是同步代码块,常用在多线程中, synchronized关键字, * 同步代码块格式是:synchronized(同步对象){} * 静态代码块 先于构造代码块 先于构造方法执行 * 静态代码块 先于普通代码块 先于构造方法执行 * 构造代码块和普通代码块按照程序逻辑顺序执行 package 面试题; class HelloA{ p

彻底理解线程同步与同步代码块synchronized

1 public class Demo { 2 public static synchronized void fun1(){ 3 } 4 public synchronized void fun2(){ 5 } 6 public static void main(String args[]) throws Exception{ 7 synchronized(xxx) { 8 9 } 10 } 11 } 三种同步类型 虽然写法不同,但实际上,只有一种,就是[同步代码块].这是核心核心核心.同步方