Java中的互斥锁,了解一下...
Posted Goach的开发日记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中的互斥锁,了解一下...相关的知识,希望对你有一定的参考价值。
在 Java 的世界里面,我们平时使用最多的就是 synchronized 。但在 Java 里面还有一种互斥锁,它是通过 ReentrantLock 来实现的。那么什么是互斥锁呢,先来看一个例子。
开启三个线程,它们的 ID 分别为 A,B,C。然后依次轮训打印他们的 ID 。这样来回打印 10 次
这是一个面试题目,如果通过 synchronized 来实现的话,代码如下:
public class ThreadTest {
public static void main(String[] args) {
Loop loop = new Loop();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
loop.thread1();
}
System.out.println("线程1退出");
}
}, "A").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
loop.thread2();
}
System.out.println("线程2退出");
}
}, "B").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
loop.thread3();
}
System.out.println("线程3退出");
}
}, "C").start();
}
private static final class Loop {
private static int num = 0;
private final Object lock = new Object();
private void thread1() {
synchronized (lock) {
if (num == 1 || num == 2) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("线程1" + Thread.currentThread().getName());
num = 1;
lock.notifyAll();
}
}
}
private void thread2() {
synchronized (lock) {
if (num == 0 || num == 2) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("线程2" + Thread.currentThread().getName());
num = 2;
lock.notifyAll();
}
}
}
private void thread3() {
synchronized (lock) {
if (num == 0 || num == 1) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("线程3" + Thread.currentThread().getName());
num = 0;
lock.notifyAll();
}
}
}
}
}
虽然能基本上实现,但是当一个线程通知其他线程的时候,其他两个线程会同时去抢这个锁,没法指定一个线程获取当前锁。而互斥锁正好有这个特点,所以我们就可以通过互斥锁来实现。
public class ThreadTest {
public static void main(String[] args) {
Loop2 loop = new Loop2();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
loop.thread1();
}
System.out.println("线程1退出");
}
}, "A").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
loop.thread2();
}
System.out.println("线程2退出");
}
}, "B").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
loop.thread3();
}
System.out.println("线程3退出");
}
}, "C").start();
}
/**
* 互斥锁
*/
private static final class Loop2 {
private static int num = 0;
private final Lock lock = new ReentrantLock();
private final Condition tread1Condition = lock.newCondition();
private final Condition tread2Condition = lock.newCondition();
private final Condition tread3Condition = lock.newCondition();
private void thread1() {
lock.lock();
try {
if (num != 0) {
tread1Condition.await();
}
System.out.println("线程1" + Thread.currentThread().getName());
num = 1;
tread2Condition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
private void thread2() {
lock.lock();
try {
if (num != 1) {
tread2Condition.await();
}
System.out.println("线程2" + Thread.currentThread().getName());
num = 2;
tread3Condition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
private void thread3() {
lock.lock();
try {
if(num != 2){
tread3Condition.await();
}
System.out.println("线程3" + Thread.currentThread().getName());
num = 0;
tread1Condition.signal();
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
上面的 Condition 是 ReentrantLock 的一个约束条件,它包括 await , sigal 等方法来指定某个线程获取锁。
总结
互斥锁可以指定某个线程获取锁,并同步
互斥锁是通过 ReentrantLock + Condition 来实现的
互斥锁一般有 await 和 signal 等方法来通信
以上是关于Java中的互斥锁,了解一下...的主要内容,如果未能解决你的问题,请参考以下文章