前言
Lock 锁是
java.util.concurrent.locks
中类,控制线程同步。
synchronized 与Lock
- 两者都可以用来锁线程,控制线程同步
- synchronized 是一个关键字,可以用来锁类、方法、代码块。线程执行完毕,synchronized 会自动释放锁,线程发生异常时也会释放,不影响后续线程
- Lock 是
java.util.concurrent.locks
一个类,能实现锁的精准控制,提供的方法比较多。Lock不会自动释放锁,加完锁后必须要释放,否则发生死锁
- synchronized 是一种非公平锁,Lock 锁可以通过公平锁
- 两个线程中,如果是synchronized 锁,当A 线程获得锁并发生阻塞时,B线程一直会等待,死等。 Lock锁,A获取锁发生阻塞时,B可以尝试获取锁,获取失败后,就放弃
Lock
lock 实现精准控制,结合Condition一起使用,先了解一下Condition
- 在java中,对于任意一个java对象,它都拥有一组定义在java.lang.Object上监视器方法,包括wait(),wait(long timeout),notify(),notifyAll(),这些方法配合synchronized关键字一起使用可以实现等待/通知模式。
- Condition接口也提供了类似Object监视器的方法,通过与Lock配合来实现等待/通知模式。
模拟3个线程按照A、B、C依次执行
public class ConditionDemo {
public static void main(String[] args) {
LockTest testLock = new LockTest();
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
testLock.test1();
} catch (Exception e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
testLock.test2();
} catch (Exception e) {
e.printStackTrace();
}
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
testLock.test3();
} catch (Exception e) {
e.printStackTrace();
}
}
}, "C").start();
}
}
/**
* lock
*/
class LockTest {
private int num = 1;
Lock lock = new ReentrantLock();
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
Condition c3 = lock.newCondition();
public void test1() {
lock.lock();
try {
while (num != 1) {
c1.await();
}
for (int i = 0; i < 2; i++) {
System.out.println("线程" + Thread.currentThread().getName() + " " + i);
}
c2.signal();
num = 2;
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void test2() {
lock.lock();
try {
while (num != 2) {
c2.await();
}
for (int i = 0; i < 4; i++) {
System.out.println("线程" + Thread.currentThread().getName() + " " + i);
}
c3.signal();
num = 3;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void test3() {
lock.lock();
try {
while (num != 3) {
c3.await();
}
for (int i = 0; i < 6; i++) {
System.out.println("线程" + Thread.currentThread().getName() + " " + i);
}
c1.signal();
num = 1;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
Lock 配置Condition 使用,某个线程执行完毕后,可以精确调度想要执行的线程。sychronized 是无法精准控制