4.3原子性-锁

实现锁可使用:

  • synchronized关键字:依赖JVM实现

  • Lock:依赖特殊的CPU指令,代码实现。 如:ReentrantLock

Synchronized

1.修饰对象及作用范围

  • 修饰代码块:大括号括起来的代码,作用于调用的对象

  • 修饰方法:整个方法,作用于调用的对象

  • 修饰静态方法:整个静态方法,作用于所有对象

  • 修饰类:括号括起来的部分,作用于所有对象

2.无Synchronized修饰的代码

实验代码

package com.moluo.concurrency.sync;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class NoSynchronizedExample {

    public static void test(String tag) {
        for (int i = 0; i < 10; i++) {
            System.out.println("tag: " + tag + ", output:" + i);
        }
    }

    public static void main(String[] args) {
        // 案例一:1个对象,2个线程,在运行程序过程中,执行权可能被夺走
        NoSynchronizedExample example = new NoSynchronizedExample();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(() -> {
            example.test("......");
        });
        executorService.execute(() -> {
            example.test(">>>>>>");
        });
        executorService.shutdown();
    }
}

输出结果

注意:由于代码的随机性,仅运行一次代码,你可能看不到执行权被夺走的情况,建议将循环次数10调到1000,却多次运行代码观察

结论

多个线程争抢cpu执行权,谁抢到算谁的。抢到执行权的线程在运行程序过程中执行权可能被夺走

3.修饰代码块:大括号括起来的代码,作用于调用的对象

实验代码

案例一输出结果

案例二输出结果

注意:由于代码的随机性,仅运行一次代码,你可能看不到执行权被夺走的情况,建议将循环次数10调到1000,却多次运行代码观察

结论

被synchronized修饰的代码块作用域为调用的对象。一个对象可以保证线程安全,两个对象无法保证线程安全

4.修饰方法:整个方法,作用于调用的对象

实验代码

案例一输出结果

案例二输出结果

结论

被synchronized修饰的方法作用域为调用的对象。一个对象可以保证线程安全,两个对象无法保证线程安全

5.修饰静态方法:整个静态方法,作用于所有对象

实验代码

案例一输出结果

案例二输出结果

结论

被synchronized修饰的静态方法作用域为所有对象。一个对象可以保证线程安全,多个对象也可保证线程安全

6.修饰类:括号括起来的部分,作用于所有对象

实验代码

案例一输出结果:

案例二输出结果:

结论

被synchronized修饰的类作用域为所有对象。一个对象可以保证线程安全,多个对象也可保证线程安全

Last updated

Was this helpful?