> For the complete documentation index, see [llms.txt](https://moluo.gitbook.io/notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://moluo.gitbook.io/notes/bian-cheng-xue-xi/java/java-gao-bing-fa/4.3-yuan-zi-xing-suo.md).

# 4.3原子性-锁

实现锁可使用:

* synchronized关键字：依赖JVM实现
* Lock：依赖特殊的CPU指令，代码实现。 如:ReentrantLock

## Synchronized

### 1.修饰对象及作用范围

* 修饰代码块：大括号括起来的代码，作用于调用的对象
* 修饰方法：整个方法，作用于调用的对象
* 修饰静态方法：整个静态方法，作用于所有对象
* 修饰类：括号括起来的部分，作用于所有对象

### 2.无Synchronized修饰的代码

#### 实验代码

```java
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();
    }
}
```

#### 输出结果

```java
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: >>>>>>, output:0  // 执行权被夺走
tag: ......, output:8
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: ......, output:9
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: >>>>>>, output:9
```

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

#### 结论

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

### 3.修饰代码块：大括号括起来的代码，作用于`调用的对象`

#### 实验代码

```java
package com.moluo.concurrency.sync;

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

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

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

        // 案例二：2个对象，2个线程，在运行程序过程中,执行权可能被夺走
        SynchronizedCodeBlockExample example1 = new SynchronizedCodeBlockExample();
        SynchronizedCodeBlockExample example2 = new SynchronizedCodeBlockExample();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(() -> {
            example1.test("......");
        });
        executorService.execute(() -> {
            example2.test(">>>>>>");
        });
        executorService.shutdown();
    }
}
```

#### 案例一输出结果

```java
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: ......, output:9
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: >>>>>>, output:9
```

#### 案例二输出结果

```java
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: ......, output:9 //执行权被夺走
tag: >>>>>>, output:9
```

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

#### 结论

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

### 4.修饰方法：整个方法，作用于`调用的对象`

#### 实验代码

```java
package com.moluo.concurrency.sync;

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

/**
 * @author moluo
 * @since 2020/6/27
 */
public class SynchronizedMethodExample {
    public synchronized 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个线程，在运行程序过程中,执行权不可被夺走
        SynchronizedMethodExample example = new SynchronizedMethodExample();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(() -> {
            example.test("......");
        });
        executorService.execute(() -> {
            example.test(">>>>>>");
        });
        executorService.shutdown();

        // two object，cross execute
//        SynchronizedMethodExample example1 = new SynchronizedMethodExample();
//        SynchronizedMethodExample example2 = new SynchronizedMethodExample();
//        ExecutorService executorService = Executors.newCachedThreadPool();
//        executorService.execute(() -> {
//            example1.test("......");
//        });
//        executorService.execute(() -> {
//            example2.test(">>>>>>");
//        });
//        executorService.shutdown();
    }

}
```

#### 案例一输出结果

```java
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: ......, output:9
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: >>>>>>, output:9
```

#### 案例二输出结果

```java
tag: ......, output:0
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: ......, output:1 // 执行权被夺走
tag: ......, output:2
tag: >>>>>>, output:8
tag: >>>>>>, output:9
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: ......, output:9
```

#### 结论

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

### 5.修饰静态方法：整个静态方法，作用于`所有对象`

#### 实验代码

```java
package com.moluo.concurrency.sync;

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

public class SynchronizedStaticMethodExample {

    public static synchronized 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个线程，在运行程序过程中,执行权不可被夺走
//        SynchronizedStaticMethodExample example = new SynchronizedStaticMethodExample();
//        ExecutorService executorService = Executors.newCachedThreadPool();
//        executorService.execute(() -> {
//            example.test("......");
//        });
//        executorService.execute(() -> {
//            example.test(">>>>>>");
//        });
//        executorService.shutdown();

        // 案例二：2个对象，2个线程，在运行程序过程中,执行权不可被夺走
        SynchronizedStaticMethodExample example1 = new SynchronizedStaticMethodExample();
        SynchronizedStaticMethodExample example2 = new SynchronizedStaticMethodExample();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(() -> {
            example1.test("......");
        });
        executorService.execute(() -> {
            example2.test(">>>>>>");
        });
        executorService.shutdown();
    }

}
```

#### 案例一输出结果

```java
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: ......, output:9
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: >>>>>>, output:9
```

#### 案例二输出结果

```java
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: ......, output:9
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: >>>>>>, output:9
```

#### 结论

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

### 6.修饰类：括号括起来的部分，作用于`所有对象`

#### 实验代码

```java
package com.moluo.concurrency.sync;

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

public class SynchronizedClassExample {

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

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

        // 案例二：2个对象，2个线程，在运行程序过程中,执行权不可被夺走
        SynchronizedClassExample example1 = new SynchronizedClassExample();
        SynchronizedClassExample example2 = new SynchronizedClassExample();
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(() -> {
            example1.test("......");
        });
        executorService.execute(() -> {
            example2.test(">>>>>>");
        });
        executorService.shutdown();
    }

}
```

#### 案例一输出结果：

```java
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: ......, output:9
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: >>>>>>, output:9
```

#### 案例二输出结果：

```java
tag: ......, output:0
tag: ......, output:1
tag: ......, output:2
tag: ......, output:3
tag: ......, output:4
tag: ......, output:5
tag: ......, output:6
tag: ......, output:7
tag: ......, output:8
tag: ......, output:9
tag: >>>>>>, output:0
tag: >>>>>>, output:1
tag: >>>>>>, output:2
tag: >>>>>>, output:3
tag: >>>>>>, output:4
tag: >>>>>>, output:5
tag: >>>>>>, output:6
tag: >>>>>>, output:7
tag: >>>>>>, output:8
tag: >>>>>>, output:9
```

#### 结论

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