LockSupport(锁支持):
四步走
来源
LockSupport 的本质:
就是用于线程等待唤醒机制的加强版本-->改良版本其中有两个特别的方法;
就是 wait()和 notify()的方法;
其中 object 类来说,wait()是让线程等待,notify()将线程唤醒;
juc 中 condition 的 await()让线程等待,使用 signal()方法唤醒线程;
标准的实现,生产者和消费者的模型:
1.利用 wait()和 notify()方法-->synchronized 的关键字,铁三角缺一不可:
package com.atguowang.thirdinterview.juc;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import java.util.concurrent.locks.LockSupport;
/**
* @author lucas
* @time 2020/10/27/10:29
* @description 锁对象,是什么,能干嘛,从哪里下,怎么玩
* AB学习法
**/
public class TestLockSupport {
//锁对象
static Object data = new Object();
public static void main(String[] args) {
//打印
//System.out.println(Thread.currentThread().getName()+"\t"+"正在运行的线程");
new Thread(() -> {
synchronized (data) {
System.out.println(Thread.currentThread().getName() + "\t" + "---线程come in");
try {
data.wait(); //等待操作
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t" + "被唤醒");
}
}, "A").start();
//第二个线程开始唤醒;
new Thread(() -> {
synchronized (data) {
data.notify();
System.out.println(Thread.currentThread().getName() + "\t" + "通知");
}
}, "B").start();
}
}
复制代码
解析:
当线程新建进入的时候,come in ,然后经过 wait 方法,,只能等着被 notify 之后,才可以执行后面的代码,、这里 synchronized 的锁对象是同一个,所以,其他的线程进入的时候可以直接,唤醒,也就是多个线程可以对可重入锁的(共同锁对象进行等待和唤醒),
异常情况 1:如果我们将 synchronized 直接删除掉,只是单纯的保留着 wait 和 notify(),还可以正常工作吗?
不能进入 wait;
Exception in thread "A" Exception in thread "B" java.lang.IllegalMonitorStateException
package com.atguowang.thirdinterview.juc;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import java.util.concurrent.locks.LockSupport;
/**
* @author lucas
* @time 2020/10/27/10:29
* @description 锁对象,是什么,能干嘛,从哪里下,怎么玩
* AB学习法
**/
public class TestLockSupport {
//锁对象
static Object data = new Object();
public static void main(String[] args) {
//打印
//System.out.println(Thread.currentThread().getName()+"\t"+"正在运行的线程");
new Thread(() -> {
// synchronized (data) {
System.out.println(Thread.currentThread().getName() + "\t" + "---线程come in");
try {
data.wait(); //等待操作
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t" + "被唤醒");
// }
}, "A").start();
//第二个线程开始唤醒;
new Thread(() -> {
// synchronized (data) {
data.notify();
System.out.println(Thread.currentThread().getName() + "\t" + "通知");
// }
}, "B").start();
}
}
复制代码
第二种情况异常:
如果我们将线程 wait->notify 的方法调换,先唤醒然后等待,会有什么异常呢
这种可以使用先让等待线程睡三秒,优先去执行唤醒的线程,试一下;
package com.atguowang.thirdinterview.juc;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import java.sql.Time;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
/**
* @author lucas
* @time 2020/10/27/10:29
* @description 锁对象,是什么,能干嘛,从哪里下,怎么玩
* AB学习法
**/
public class TestLockSupport {
//锁对象
static Object data = new Object();
public static void main(String[] args) {
new Thread(() -> {
//暂停几秒钟
try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }
synchronized (data) {
System.out.println(Thread.currentThread().getName() + "\t" + "---线程come in");
try {
data.wait(); //等待操作
} catch (InterruptedException e) {
e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + "\t" + "被唤醒"); }
}, "A").start();
//第二个线程开始唤醒;
new Thread(() -> {
synchronized (data) {
data.notify();
System.out.println(Thread.currentThread().getName() + "\t" + "通知");
}
}, "B").start();
}
}
复制代码
表示的时候--铁三角不能打破,或者说;wait 和 notify 的位置不能改变,如果说,一个线程中不能改变-->wait --->
package com.atguowang.thirdinterview.juc;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import java.sql.Time;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
/**
* @author lucas
* @time 2020/10/27/10:29
* @description 锁对象,是什么,能干嘛,从哪里下,怎么玩
* AB学习法
**/
public class TestLockSupport {
//锁对象
static Object data = new Object();
public static void main(String[] args) {
new Thread(() -> {
//暂停几秒钟
//try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }
synchronized (data) {
System.out.println(Thread.currentThread().getName() + "\t" + "---线程come in");
try { data.wait(); //等待操作
System.out.println("处于被等待的状态");
data.notify();
System.out.println("处于一个唤醒的状态");
} catch (InterruptedException e) {
e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + "\t" + "被唤醒"); }
}, "A").start();
// 第二个线程开始唤醒;
new Thread(() -> {
synchronized (data) {
data.notify();
System.out.println(Thread.currentThread().getName() + "\t" + "通知");
}
}, "B").start();
}
}
复制代码
还得保证具体的数据,我们将线程的转化为具体的使用,方法是一个简单的过程,如果说一个对象我们可以得到;
ReentrantLock 是 java.util.concurrent.Locks.ReentrantLock 的比较数据,然后我们将使用的过程直接变成具体的数据;这个对于重入互斥锁,synchronized 的扩展,
因为他有具体的 condition 的一个锁的状态--
ReentrantLock ----》代表的 await()和具体的 signal();
其中使用的 await()等方式就是在利用状态(condition)是一个接口。里面有默认的方法和具体的唤醒--等待阻塞;
lock()-->sync.lock()---》AQS
AbstractQueuedSynchronizer --》AQSAbstractQueuedSychronzier 查看 LockSupport 的显示结果--可以成为具体的数据展示;
JUC-->AQS-->LockSupport
卢卡寄语
当前可重入锁的底层 AQS,在底层就是锁支持,所以对于锁来说, 分类搞懂以后,对于最底层的知识,以不变应万变才是做好的,
晚安啦,我是卢卡,看完记得点赞哦
评论