目录
JUC下的锁:lock.lock()锁
synchronized是一种非常早期的锁,后期重新进行的设计,以类和对象的形式使用(不在语言层面)。在java.util.concurrent.* JUC包<-现代写Java并发编程尽量使用这个包下提供的工具。
lock锁相较于sync锁更加灵活:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main1 {
private static final Lock lock = new ReentrantLock();
static class MyThread extends Thread {
@Override
public void run() {
//锁被主线程持有 主线程也不释放锁,所以这里永远加不到锁
lock.lock();
//加锁成功才会执行
System.out.println("子线程进入临界区"); // 理论上,这句代码永远到达不了
}
}
public static void main(String[] args) throws InterruptedException {
//主线程加锁 这句一定会先执行
lock.lock();
MyThread t = new MyThread();
t.start();
t.join();
}
}
Main1也演示了一种现象----死锁(Dead Lock)这里的死锁和OS得死锁不太一样(现象上都是卡住了),但是不是资源分配得问题。主线程在调用t1.join()在等子线程结束,子线程在调用lock.lock() 在等主线程释放锁,主线程持有锁。
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main2 {
private static final Lock lock = new ReentrantLock();
static class MyThread extends Thread {
@Override
public void run() {
lock.lock();
System.out.println("子线程进入临界区"); // 理论上,这句代码永远到达不了
}
}
public static void main(String[] args) throws InterruptedException {
lock.lock();
MyThread t = new MyThread();
t.start();
//等两秒
TimeUnit.SECONDS.sleep(2);
//interrupt()意思:发消息告诉t1线程应该结束了。至于t1线程自己能不能收到这个消息
得看t1当时在干嘛,如果t1在执行lock.lock();没法获得消息
//interrupt()本质上和锁没关系
t.interrupt(); // 尝试让子线程停下来,但实际会徒劳无功
t.join();
}
}
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main3 {
private static final Lock lock = new ReentrantLock();
static class MyThread extends Thread {
@Override
public void run() {
try {
//这个方法的结束情况:1.不限时等待直到加锁,等待过程可能是永远。
2.在请求锁的过程中,由于线程被中止,导致方法结束,抛出InterruptedException形式体现 异常代码段
lock.lockInterruptibly();
System.out.println("子线程进入临界区"); // 理论上,这句代码永远到达不了
} catch (InterruptedException e) {
System.out.println("收到停止信号,停止运行");
}
}
}
public static void main(String[] args) throws InterruptedException {
lock.lock();
MyThread t = new MyThread();
t.start();
//等2s后 让线程停止 但是没有释放锁 导致子线程异常结束
TimeUnit.SECONDS.sleep(2);
//interrupt()意思:发消息告诉t1线程应该结束了。至于t1线程自己能不能收到这个消息
得看t1当时在干嘛,如果t1在执行lock.lock();没法获得消息
//interrupt()本质上和锁没关系
t.interrupt();
t.join();
}
}
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main4 {
private static final Lock lock = new ReentrantLock();
static class MyThread extends Thread {
@Override
public void run() {
boolean b = lock.tryLock();
if (b == true) {
// 加锁成功了
System.out.println("加锁成功");
System.out.println("子线程进入临界区"); // 理论上,这句代码永远到达不了
} else {
System.out.println("加锁失败");
}
}
}
public static void main(String[] args) throws InterruptedException {
lock.lock();
MyThread t = new MyThread();
t.start();
TimeUnit.SECONDS.sleep(2);
//interrupt()意思:发消息告诉t1线程应该结束了。至于t1线程自己能不能收到这个消息
得看t1当时在干嘛,如果t1在执行lock.lock();没法获得消息
//interrupt()本质上和锁没关系
t.interrupt(); // 尝试让子线程停下来,但实际会徒劳无功
t.join();
}
}
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main5 {
private static final Lock lock = new ReentrantLock();
static class MyThread extends Thread {
@Override
public void run() {
boolean b = false;
try {
//等5s,加锁正常返回true 没加上锁正常返回false
//要不就是 在5s等待时间中,线程被终止,就返回异常终止代码
b = lock.tryLock(5, TimeUnit.SECONDS);
if (b == true) {
// 加锁成功了
System.out.println("加锁成功");
System.out.println("子线程进入临界区"); // 理论上,这句代码永远到达不了
} else {
System.out.println("5s 之后加锁失败");
}
} catch (InterruptedException e) {
System.out.println("被人打断了");
}
}
}
public static void main(String[] args) throws InterruptedException {
lock.lock();
MyThread t = new MyThread();
t.start();
TimeUnit.SECONDS.sleep(2);
// t.interrupt(); // 尝试让子线程停下来,但实际会徒劳无功
//主线程2S后释放锁
lock.unlock();
t.join();
}
}
synchronized锁 vs JUC下的锁
synchronized锁:代码书写就保证一定有锁的释放,synchronized(锁){...};只有一种类型的锁;synchronized只能一直请求锁。
juc下的锁:是可能忘记写lock.unlock()导致锁一直不释放的,书写更灵活,可以在一个方法中加锁,另一个方法中解锁;锁的类型更加灵活:公平锁、非公平锁、读写锁、独占锁、可重入锁、不可重入锁.;锁的加锁策略更灵活:1.一直请求锁。2.带中断。3.尝试请求。4.带超时的尝试。
请求锁失败后的线程的阻塞状态
请求锁失败后的线程阻塞状态不同:
blocked:专指请求synchronized锁失败时的状态。
waiting:lock.lock();lock.lockInterruptly();t.join();
timed_waiting:一般带时间,Thread.sleep()、t.join()、lock.trylock();