在Java中,锁的概念都是基于对象的,所以我们⼜经常称它为对象锁。线程和锁的关系,我们可以⽤婚姻关系来理解。⼀个锁同⼀时间只能被⼀个线程持有。也就是说,⼀个锁如果和⼀个线程“结婚”(持有),那其他线程如果需要得到这个锁,就得等这个线程和这个锁“离婚”(释放)。
在我们的线程之间,有⼀个同步的概念。什么是同步呢,假如我们现在有2位正在抄暑假作业答案的同学:线程A和线程B。当他们正在抄的时候,⽼师突然来修改了⼀些答案,可能A和B最后写出的暑假作业就不⼀样。我们为了A,B能写出2本相同的暑假作业,我们就需要让⽼师先修改答案,然后A,B同学再抄。或者A,B同学先抄完,⽼师再修改答案。这就是线程A,线程B的线程同步。
可以以解释为:线程同步是线程之间按照⼀定的顺序执⾏。
为了达到线程同步,我们可以使⽤锁来实现它。
我们先来看看⼀个⽆锁的程序:
package com.company;
import java.util.stream.IntStream;
public class NoneLock {
static class ThreadA implements Runnable {
@Override
public void run() {
IntStream.range(1, 100).forEach(i -> {
System.out.println("threadA:" + i);
});
}
}
static class ThreadB implements Runnable {
@Override
public void run() {
IntStream.range(1, 100).forEach(i -> {
System.out.println("threadB:" + i);
});
}
}
public static void main(String[] args) {
new Thread(new ThreadA()).start();
new Thread(new ThreadB()).start();
}
}
某次的运行结果
那我现在有⼀个需求,我想等A先执⾏完之后,再由B去执⾏,怎么办呢?最简单的⽅式就是使⽤⼀个“对象锁”:
package com.company;
import java.util.stream.IntStream;
public class ObjectLock {
private static final Object lock = new Object();
static class ThreadA implements Runnable {
@Override
public void run() {
synchronized (lock) {
IntStream.range(1, 100).forEach(i -> {
System.out.println("threadA:" + i);
});
}
}
}
static class ThreadB implements Runnable {
@Override
public void run() {
synchronized (lock) {
IntStream.range(1, 100).forEach(i -> {
System.out.println("threadB:" + i);
});
}
}
}
public static void main(String[] args) throws InterruptedException {
new Thread(new ThreadA()).start();
Thread.sleep(10);
new Thread(new ThreadB()).start();
}
}
不知道能不能用?
呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃