JAVA同步锁 synchronized(this)、synchronized(class)与synchronized(Object)的区别

简介: 利用实例介绍JAVA同步锁 synchronized(this)、synchronized(class)与synchronized(Object)的区别
/**
 * synchronized(this) 只能锁当前对象
 * synchronized(A.class) 锁类,对类的所有实例生效
 */

public class Synchronized {
    public void method1() { // 锁当前对象
        try {
            synchronized (this) {
                System.out.println("this   method1 start time=" + System.currentTimeMillis());
                Thread.sleep(2000);
                System.out.println("this   method1 end time=" + System.currentTimeMillis());
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public synchronized void method2() { // 与method1存在竞争关系
        System.out.println("       method2 start time=" + System.currentTimeMillis());
        System.out.println("       method2 end time=" + System.currentTimeMillis());
    }

    public void method3() { // 锁类,对类的所有实例生效
        synchronized (Synchronized.class) {
            try {
                System.out.println("class  method3 start time=" + System.currentTimeMillis());
                Thread.sleep(4000);
                System.out.println("class  method3 end time=" + System.currentTimeMillis());
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static synchronized void method4() { // 与method3存在竞争关系
        System.out.println("static method4 start time=" + System.currentTimeMillis());
        System.out.println("static method4 end time=" + System.currentTimeMillis());
    }

}

class Thread1 extends Thread {
    private Synchronized objectService;

    public Thread1(Synchronized objectService) {
        super();
        this.objectService = objectService;
    }

    @Override
    public void run() {
        super.run();
        objectService.method1();
    }
}

class Thread2 extends Thread {
    private Synchronized objectService;

    public Thread2(Synchronized objectService) {
        super();
        this.objectService = objectService;
    }

    @Override
    public void run() {
        super.run();
        objectService.method2();
    }
}

class Thread3 extends Thread {
    private Synchronized objectService;

    public Thread3(Synchronized objectService) {
        super();
        this.objectService = objectService;
    }

    @Override
    public void run() {
        super.run();
        objectService.method3();
    }
}

class Thread4 extends Thread {
    private Synchronized objectService;

    public Thread4(Synchronized objectService) {
        super();
        this.objectService = objectService;
    }

    @Override
    public void run() {
        super.run();
        objectService.method4();
    }
}

class MainTest {
    public static void main(String[] args) {
        Synchronized service = new Synchronized();

        new Thread1(service).start();
        new Thread2(service).start();
        new Thread3(service).start();
        new Thread4(service).start();
    }
}

输出结果:

在这里插入图片描述
从时间线可以看出method1method2method3method4存在竞争关系。
当一个线程访问Synchronized类的一个synchronized (this)同步代码块时,其它线程对同一个Synchronized类中其它的synchronized ()同步方法的访问将是堵塞;访问synchronized (Synchronized.class)同步代码块时, static synchronized同步方法的访问将是阻塞,这说明synchronized (this)和synchronized ()同步方法、synchronized (Synchronized.class)同步代码块和 static synchronized同步方法使用的对象监视器是一个。

synchronized同步方法和synchronized(this)同步代码块

/**
 * synchronized(this)锁定当前对象
 */

public class SynchronizedThis {
    public void methodA() {
        try {
            synchronized (this) {
                System.out.println("this methodA 线程名称:" + Thread.currentThread().getName() + " begin time=" + System.currentTimeMillis());
                for (int i = 1; i <= 2; i++) {
                    System.out.println("this methodA 线程名称:" + Thread.currentThread().getName() + "-->i=" + i);
                    Thread.sleep(100);
                }
                System.out.println("this methodA 线程名称:" + Thread.currentThread().getName() + " end  time=" + System.currentTimeMillis());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void methodB() {
        synchronized (this) {
            try {
                System.out.println("this methodB 线程名称:" + Thread.currentThread().getName() + " begin time=" + System.currentTimeMillis());
                for (int i = 1; i <= 2; i++) {
                    System.out.println("this methodB 线程名称:" + Thread.currentThread().getName() + "-->i=" + i);
                    Thread.sleep(100);
                }
                System.out.println("this methodB 线程名称:" + Thread.currentThread().getName() + " end  time=" + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public synchronized void methodC() {
        try {
            System.out.println("     methodC 线程名称:" + Thread.currentThread().getName() + " begin time=" + System.currentTimeMillis());
            for (int i = 1; i <= 2; i++) {
                System.out.println("     methodC 线程名称:" + Thread.currentThread().getName() + "-->i=" + i);
                Thread.sleep(100);
            }
            System.out.println("     methodC 线程名称:" + Thread.currentThread().getName() + " end  time=" + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class ThisThreadA extends Thread {
    private SynchronizedThis synchronizedThis;

    public ThisThreadA(SynchronizedThis synchronizedThis) {
        super();
        this.synchronizedThis = synchronizedThis;
    }

    @Override
    public void run() {
        super.run();
        synchronizedThis.methodA();
    }
}

class ThisThreadB extends Thread {
    private SynchronizedThis synchronizedThis;

    public ThisThreadB(SynchronizedThis synchronizedThis) {
        super();
        this.synchronizedThis = synchronizedThis;
    }

    @Override
    public void run() {
        super.run();
        synchronizedThis.methodB();
    }
}

class ThisThreadC extends Thread {
    private SynchronizedThis synchronizedThis;

    public ThisThreadC(SynchronizedThis synchronizedThis) {
        super();
        this.synchronizedThis = synchronizedThis;
    }

    @Override
    public void run() {
        super.run();
        synchronizedThis.methodC();
    }
}

class ThisMainTest {
    public static void main(String[] args) {
        SynchronizedThis service = new SynchronizedThis();
        ThisThreadA a = new ThisThreadA(service);
        a.setName("ThreadA");
        a.start();
        ThisThreadB b = new ThisThreadB(service);
        b.setName("ThreadB");
        b.start();
        ThisThreadC c = new ThisThreadC(service);
        c.setName("ThreadC");
        c.start();
    }
}

输出结果
在这里插入图片描述

多个线程调用同一个对象中的不同名称的synchronized同步方法或synchronized(this)同步代码块时,是同步的。

synchronized同步方法synchronized(this)同步代码块是相互竞争关系

  1. 对其它的synchronized同步方法或synchronized(this)同步代码块调用是堵塞状态;
  2. 同一时间只有一个线程执行synchronized同步方法或synchronized(this)同步代码块中的代码。

静态同步synchronized方法

/**
 * 静态同步synchronized方法
 * synchronized应用在static方法上,那是对当前对应的*.Class进行持锁。
 */
public class SynchronizedStatic {
    public synchronized static void methodA() {
        try {
            System.out.println("static methodA 线程名称:" + Thread.currentThread().getName() + " begin times:" + System.currentTimeMillis());
            for (int i = 1; i <= 5; i++) {
                System.out.println("static methodA 线程名称:" + Thread.currentThread().getName() + "-->i=" + i);
                Thread.sleep(1000);
            }
            System.out.println("static methodA 线程名称:" + Thread.currentThread().getName() + " end   times:" + System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized static void methodB() {
        System.out.println("static methodB 线程名称:" + Thread.currentThread().getName() + " begin times:" + System.currentTimeMillis());
        System.out.println("static methodB 线程名称:" + Thread.currentThread().getName() + " end   times:" + System.currentTimeMillis());
    }
}

class StaticThreadA extends Thread {
    @Override
    public void run() {
        SynchronizedStatic.methodA();
    }
}

class StaticThreadB extends Thread {
    @Override
    public void run() {
        SynchronizedStatic.methodB();
    }
}

class StaticMainTest {
    public static void main(String[] args) {
        StaticThreadA a = new StaticThreadA();
        a.setName("ThreadA");
        a.start();
        StaticThreadB b = new StaticThreadB();
        b.setName("ThreadB");
        b.start();
    }
}

输出结果
在这里插入图片描述
synchronized应用在static方法上,那是对当前对应的.Class进行持锁,与同步synchronized(.class)代码块作用一样。
对比下面代码进行验证

synchronized(*.class)代码块

/**
 * synchronized(*.class)代码块
 * 同步synchronized(*.class)代码块的作用其实和synchronized static方法作用一样。
 * Class锁对类的所有对象实例起作用。
 */
public class SynchronizedClass {
    public void methodA() {
        try {
            synchronized (SynchronizedClass.class) {
                System.out.println("class methodA 线程名称:" + Thread.currentThread().getName() + " begin times:" + System.currentTimeMillis());
                for (int i = 1; i <= 5; i++) {
                    System.out.println("class methodA 线程名称:" + Thread.currentThread().getName() + "-->i=" + i);
                    Thread.sleep(1000);
                }
                System.out.println("class methodA 线程名称:" + Thread.currentThread().getName() + " end   times:" + System.currentTimeMillis());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void methodB() {
        synchronized (SynchronizedClass.class) {
            System.out.println("class methodB 线程名称:" + Thread.currentThread().getName() + " begin times:" + System.currentTimeMillis());
            System.out.println("class methodB 线程名称:" + Thread.currentThread().getName() + " end   times:" + System.currentTimeMillis());
        }
    }
}

class ClassThreadA extends Thread {
    private SynchronizedClass objectService;

    public ClassThreadA(SynchronizedClass objectService) {
        super();
        this.objectService = objectService;
    }

    @Override
    public void run() {
        objectService.methodA();
    }
}

class ClassThreadB extends Thread {
    private SynchronizedClass objectService;

    public ClassThreadB(SynchronizedClass objectService) {
        super();
        this.objectService = objectService;
    }

    @Override
    public void run() {
        objectService.methodB();
    }
}

class ClassMainTest {
    public static void main(String[] args) {
        SynchronizedClass service = new SynchronizedClass();
        ClassThreadA a = new ClassThreadA(service);
        a.setName("ThreadA");
        a.start();
        ClassThreadB b = new ClassThreadB(service);
        b.setName("ThreadB");
        b.start();
    }
}

// Class锁对类的所有对象实例起作用。
class ClassMainTest2 {
    public static void main(String[] args) {
        SynchronizedClass service1 = new SynchronizedClass();
        SynchronizedClass service2 = new SynchronizedClass();
        ClassThreadA a = new ClassThreadA(service1);
        a.setName("ThreadA-service1");
        a.start();
        ClassThreadB b = new ClassThreadB(service2);
        b.setName("ThreadB-service2");
        b.start();
    }
}

输出结果
在这里插入图片描述

同步synchronized(*.class)代码块的作用其实和synchronized static方法作用一样。
Class锁对类的所有对象实例起作用。

目录
相关文章
|
18天前
|
Java 程序员
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
48 14
|
13天前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
18 1
|
23天前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
42 8
|
1月前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
106 4
|
1月前
|
设计模式 JavaScript 前端开发
js中new和object.creat区别
【10月更文挑战第29天】`new` 关键字和 `Object.create()` 方法在创建对象的方式、原型链继承、属性初始化以及适用场景等方面都存在差异。在实际开发中,需要根据具体的需求和设计模式来选择合适的方法来创建对象。
|
1月前
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
45 4
|
1月前
|
Java
Java代码解释++i和i++的五个主要区别
本文介绍了前缀递增(++i)和后缀递增(i++)的区别。两者在独立语句中无差异,但在赋值表达式中,i++ 返回原值,++i 返回新值;在复杂表达式中计算顺序不同;在循环中虽结果相同但使用方式有别。最后通过 `Counter` 类模拟了两者的内部实现原理。
Java代码解释++i和i++的五个主要区别
|
2月前
|
Java
通过Java代码解释成员变量(实例变量)和局部变量的区别
本文通过一个Java示例,详细解释了成员变量(实例变量)和局部变量的区别。成员变量属于类的一部分,每个对象有独立的副本;局部变量则在方法或代码块内部声明,作用范围仅限于此。示例代码展示了如何在类中声明和使用这两种变量。
|
2月前
|
算法 Java 程序员
Java中的Synchronized,你了解多少?
Java中的Synchronized,你了解多少?
|
2月前
|
Java
让星星⭐月亮告诉你,Java synchronized(*.class) synchronized 方法 synchronized(this)分析
本文通过Java代码示例,介绍了`synchronized`关键字在类和实例方法上的使用。总结了三种情况:1) 类级别的锁,多个实例对象在同一时刻只能有一个获取锁;2) 实例方法级别的锁,多个实例对象可以同时执行;3) 同一实例对象的多个线程,同一时刻只能有一个线程执行同步方法。
22 1