JUC下的锁

JUC下的锁,第1张

目录

JUC下的锁:lock.lock()锁

synchronized锁 vs JUC下的锁

请求锁失败后的线程的阻塞状态


JUC下的锁:lock.lock()锁

synchronized是一种非常早期的锁,后期重新进行的设计,以类和对象的形式使用(不在语言层面)。在java.util.concurrent.* JUC包<-现代写Java并发编程尽量使用这个包下提供的工具。

java.util.concurrent.locks:

 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();

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/868719.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存