本文通过一个例子来解释两种锁机制:实现ABC循环打印3次“ABCABCABC”,要求使用3个线程,分别打印A/B/C,通过锁同步机制来控制流程

使用对象锁

synchronized锁的是括号里的对象

public class Main {
    private static Boolean flagA = true;
    private static Boolean flagB = false;
    private static Boolean flagC = false;

    public static void main(String[] args) {
        // 使用对象锁
        final Object lock = new Object();

        Runnable taskA = () -> {
            for(int i = 0; i < 3;) {
                synchronized (lock) {
                    // 获取到了对象锁权限 
                    if (flagA) {
                        System.out.println("A");

                        flagA = false;
                        flagB = true;
                        flagC = false;
                        // 恰好是当前轮,执行完,唤醒其他线程
                        lock.notifyAll();
                        i++;
                    } else {
                        try {
                            // 还没有轮到,则继续等待
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };

        Runnable taskB = () -> {
            for(int i = 0; i < 3;) {
                synchronized (lock) {
                    if (flagB) {
                        System.out.println("B");

                        flagA = false;
                        flagB = false;
                        flagC = true;
                        lock.notifyAll();
                        i++;
                    } else {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };

        Runnable taskC = () -> {
            for(int i = 0; i < 3;) {
                synchronized (lock) {
                    if (flagC) {
                        System.out.println("C");

                        flagA = true;
                        flagB = false;
                        flagC = false;
                        lock.notifyAll();
                        i++;
                    } else {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };

        new Thread(taskA).start();
        new Thread(taskB).start();
        new Thread(taskC).start();
    }
}

使用Lock类

使用Lock类型可以做更精细的代码级别的控制

import java.util.concurrent.locks.ReentrantLock;

public class Main {
    private static Boolean flagA = true;
    private static Boolean flagB = false;
    private static Boolean flagC = false;

    public static void main(String[] args) {
        // 使用可重入锁类型
        final ReentrantLock lock = new ReentrantLock();

        Runnable taskA = () -> {
            for(int i = 0;i < 3;) {
                try {
                    // 循环竞争锁,竞争到后检查,如果是当前轮到,则处理
                    lock.lock();

                    if (flagA) {
                        System.out.println("A");

                        flagA = false;
                        flagB = true;
                        flagC = false;
                        ++i;
                    }
                } finally {
                    lock.unlock();
                }
            }
        };

        Runnable taskB = () -> {
            for(int i = 0; i < 3;) {
                try {
                    lock.lock();

                    if (flagB) {
                        System.out.println("B");

                        flagA = false;
                        flagB = false;
                        flagC = true;
                        ++i;
                    }
                } finally {
                    lock.unlock();
                }
            }
        };

        Runnable taskC = () -> {
            for(int i = 0; i < 3;) {
                try {
                    lock.lock();

                    if (flagC) {
                        System.out.println("C");

                        flagA = true;
                        flagB = false;
                        flagC = false;
                        ++i;
                    }
                } finally {
                    lock.unlock();
                }
            }
        };

        new Thread(taskA).start();
        new Thread(taskB).start();
        new Thread(taskC).start();
    }