一文总结Synchronized的各种用法并代码实现

测试Synchronized在多线程情况下的实现

首先,Synchronized修饰的对象有四种
1.修饰一个代码块
2.修饰一个静态方法
3.修饰一个实例方法
4.修饰一个类

1.用相同对象修饰代码块/方法输出测试

尝试用两次调用代码块
注:调用线程池来创建线程,因为如果不调用线程池的话,类的同一个对象ex两次调用同一个方法本身就是同步执行没法看出锁的情况。线程池创建两个线程执行代码块。

public class SynchronizedEx1 {
    // 修饰方法里的代码块
    public void test() {
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                System.out.println("test current is " +i);
            }
        }
    }
    
    public static void main(String[] args) {
        SynchronizedEx1 ex = new SynchronizedEx1();
        //用线程池
        ExecutorService exService = Executors.newCachedThreadPool();
        //开启一个线程执行方法
        exService.execute(() -> {
            ex.test();
        });
        exService.execute(() -> {
            ex.test();
        });
    }
}

由以上代码可看出,首先是执行了一遍完整的test作用的对象是调用了代码块的对象
在这里插入图片描述

2.用不同对象修饰代码块/方法输出测试

public class SynchronizedEx2 {
   // 修饰一个方法,用n来标识具体作用的对象
    public synchronized void test2(int n) {
        for (int i = 0; i < 6; i++) {
            System.out.println("test"+n+"is"+i );
        }
    }

    public static void main(String[] args) {
        SynchronizedEx2 ex1 = new SynchronizedEx2();
        SynchronizedEx2 ex2 = new SynchronizedEx2();
        ExecutorService exService = Executors.newCachedThreadPool();
        exService.execute(() -> {
            ex1.test2(1);
        });
        executorService.execute(() -> {
            ex2.test2(2);
        });
    }
}

由结果可看出,不同的对象各自的调用是互相不影响的。

在这里插入图片描述

3.用不同对象修饰类的输出测试

同一个对象调用类方法和不同对象调用类方法的执行结果一样,这里直接给出不同对象情况的代码:

public class SynchronizedEx3 {
    //用反射达到修饰类并调用执行的目的
    public static void test(int j) {
        synchronized (SynchronizedEx3.class) {
            for (int i = 0; i < 6; i++) {
                System.out.println("test"+n+"is"+i );
            }
        }
    }

    public static void main(String[] args) {
        SynchronizedEx3 ex1 = new SynchronizedEx3();
        SynchronizedEx3 ex2 = new SynchronizedEx3();
        ExecutorService exService = Executors.newCachedThreadPool();
        exService.execute(() -> {
            ex.test(1);
        });
        executorService.execute(() -> {
            ex.test(2);
        });
    }
}

执行结果是先ex1执行完后再执行ex2,可见Synchronized修饰类时是作用于所有对象的:
在这里插入图片描述
Synchronized修饰类和静态代码块一样,同一时间只有一个线程可以执行。

注:Synchronize在修饰对类,方法时并不属于可继承的特性,子类/重写方法是不会自动带有Synchronized同步性的

发布了21 篇原创文章 · 获赞 4 · 访问量 1365

猜你喜欢

转载自blog.csdn.net/smile001isme/article/details/104538097