本文通过一个例子来解释两种锁机制:实现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();
}