java锁-重用锁,自旋锁
一、重用锁
1.理论
可重入锁:线程在获取外部方法的锁对象时,会自动获取内层递归调用方法的锁。防止死锁(线程之间相互等着对方释放资源,而自己的资源又不释放给别人,这种情况就是死锁。)。常见的锁有:synchronized 与 ReentrantLock。
2.实操
package juc;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo01 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
try {
phone.sendMsg();
}catch (Exception ex){
ex.printStackTrace();
}
},"t1").start();
new Thread(()->{
try {
phone.sendMsg();
}catch (Exception ex){
ex.printStackTrace();
}
},"t2").start();
Thread t3 = new Thread(new Phone(),"t3");
Thread t4 = new Thread(new Phone(),"t4");
t3.start();
t4.start();
}
}
/**
* 共享资源
*/
class Phone implements Runnable{
// case01(synchronized)
public synchronized void sendMsg(){
sendMail();
System.out.println(Thread.currentThread().getName()+"\t sendMsg run");
}
public synchronized void sendMail(){
// sendMsg();此时出现死锁现象:线程之间相互等着对方释放资源,而自己的资源又不释放给别人,这种情况就是死锁。
System.out.println(Thread.currentThread().getName()+"\t sendMail run");
}
// case02(ReentrantLock)
@Override
public void run() {
get();
}
public void get(){
// 外层锁
Lock lock = new ReentrantLock();
try {
lock.lock();
set();
System.out.println(Thread.currentThread().getName()+"\t run get()");
}finally {
lock.unlock();
}
}
public void set(){
// 内层锁
Lock lock = new ReentrantLock();
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+"\t run set()");
}finally {
lock.unlock();
}
}
}
二、自旋锁
1.理论
采用循环尝试的方式获取锁,减少线程上下文切换的消耗,但是循环CAS操作会带来CPU消耗问题。
2.实操
package juc;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
/**
* 自旋锁;采用循环尝试的方式获取锁,减少线程上下文切换的消耗,但是循环CAS操作会带来CPU消耗问题;
*/
public class Demo02 {
public static void main(String[] args) {
Demo02 demo02 = new Demo02();
new Thread(()->{
try {
demo02.lock();
// 获取锁5s,不释放
try {
TimeUnit.SECONDS.sleep(5);
}catch (Exception ex){
ex.printStackTrace();
}
demo02.unlock();
}catch (Exception ex){
ex.printStackTrace();
}
},"t1").start();
try {
TimeUnit.SECONDS.sleep(1);
}catch (Exception ex){
ex.printStackTrace();
}
new Thread(()->{
demo02.lock();
try {
TimeUnit.SECONDS.sleep(1);
}catch (Exception ex){
ex.printStackTrace();
}
demo02.unlock();
},"t2").start();
}
// 原子引用初始值null
AtomicReference<Thread> atomicReference = new AtomicReference<>();
// 上锁
public void lock(){
Thread currentThread = Thread.currentThread();
System.out.println(currentThread.getName()+"进入");
// 循环尝试使用比较并交换原理
while (!atomicReference.compareAndSet(null,currentThread)){
System.out.println(currentThread.getName()+"\t 当前锁还未释放锁,请耐心等待");
}
System.out.println(currentThread.getName()+"\t 获取锁");
}
// 解锁
public void unlock(){
Thread currentThread = Thread.currentThread();
atomicReference.compareAndSet(currentThread,null);
System.out.println(Thread.currentThread().getName()+"\t 释放锁");
}
}