Java synchronized关键字用法

本篇随笔主要介绍 Java 中 synchronized 关键字常用法,主要有以下四个方面:

1、实例方法同步

2、静态方法同步

3、实例方法中同步块

4、静态方法中同步块

我觉得在学习synchronized关键字之前,我们首先需要知道以下一点:Java 中每个实例对象对应一把锁且每个实例对象只有一把锁,synchronized 关键字是通过对相应的实例对象加锁来实现同步功能的。

一、实例方法中使用 synchronized 加锁

实例方法中默认被加锁的对象是调用此方法的实例对象。

class ImmutableValue {
    public synchronized void comeIn() throws InterruptedException{
        System.out.println(Thread.currentThread().getName() + ": start");
        Thread.sleep(5000);
        System.out.println(Thread.currentThread().getName() + ": finish");
    }
    public  void synchronized comeInIn() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + ": start");
        Thread.sleep(5000);
        System.out.println(Thread.currentThread().getName() + ": finish");
    }
}
public class TestImmutableValue {
    public static void main(String[] args) {
        ImmutableValue im = new ImmutableValue();
        Thread t1 = new Thread(new Runnable() {

@Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    im.comeIn();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
           
        }, "t1");
        Thread t2 = new Thread(new Runnable() {

@Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    im.comeInIn();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
           
        }, "t2");
        t1.start();
        t2.start();
    }
}

在上面的代码中创建了两个线程并分别命名为 t1, t2。调用了同一个对象 im 的两个同步方法 comeIn 和 comeInIn, 执行结果如下:

Java synchronized关键字用法

在 t1 线程开始执行后,即使 t1 线程睡眠了5s,线程 t2 中的 comeInIn 方法仍然没有得到执行。这是因为 t1 线程先执行的 comeIn 方法,持有了对象 im 的锁,且 comeIn 方法并没有执行完,对象 im 的锁没有被释放,所以 comeInIn 方法无法对对象 im 加锁,就无法继续执行,只能等到 t1 线程中的 comeIn 方法执行完毕,释放对象 im 的锁,comeInIn 方法才能继续执行。

但是如果 t1 线程调用的是对象 im 的 comeIn 方法,而 t2 线程调用的是我们声明的另外一个  ImmutableValue 对象 im2 对象的 comeInIn 方法,则这两个方法的执行是互不影响的。因为 t1 线程的 comeIn 方法要获得 im 对象的锁,而 t2 线程要获得的是 im2 对象的锁,两个锁并不是同一个锁(Java中每个实例对象都有且只有一个锁),所以这两个方法执行互不影响。

二、静态方法中使用 synchronized 加锁

静态方法中默认被加锁的对象是此静态方法所在类的 class 对象。

class staticMethodSynchronized {
    public static synchronized void method1() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + ": start");
        Thread.sleep(5000);
        System.out.println(Thread.currentThread().getName() + ": finish");
    }
    public static synchronized void method2() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + ": start");
        Thread.sleep(5000);
        System.out.println(Thread.currentThread().getName() + ": finish");
    }
}
public class TestStaticClassSynchronized {
    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/98ff92272ae108682121765bfe4a0b23.html