# 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修饰的类作用域为`所有对象`。一个对象可以保证线程安全，多个对象也可保证线程安全


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://moluo.gitbook.io/notes/bian-cheng-xue-xi/java/java-gao-bing-fa/4.3-yuan-zi-xing-suo.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
