java多线程基本概述(九)——Lock(3)

java多线程基本概述(九)——Lock(3)

大家好,又见面了,我是全栈君。

Lock接口提供了三种获取锁的能力。可中断,不可中断,定时。api文档如下:

void lock()
Acquires the lock.//获取锁,
If the lock is not available then the current thread becomes disabled for thread scheduling purposes and lies dormant until the lock has been acquired.
//如果锁不可获取,那么由于线程调度器调度的意图,当前线程将被禁止,并且在锁被释放之前当前线程一致处于休眠状态。

 

void lockInterruptibly()throws InterruptedException
Acquires the lock unless the current thread is interrupted.
//如果当前线程没有被中断,那么将获得锁 Acquires the lock
if it is available and returns immediately. //如果锁可用则获取锁,并且快速返回。 If the lock is not available then the current thread becomes disabled for thread scheduling purposes and lies dormant until one of two things happens: //如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下两种情况之一以前,该线程将一直处于休眠状态: The lock is acquired by the current thread; or
//锁由当前线程获得;或者 Some other thread interrupts the current thread, and interruption of lock acquisition is supported.
//其他某个线程中断当前线程,并且支持对锁获取的中断。 If the current thread: //如果当前线程 has its interrupted status set on entry to
this method; or
//在进入此方法时已经设置了该线程的中断状态;或者 is interrupted
while acquiring the lock, and interruption of lock acquisition is supported,
//在获取锁时被中断,并且支持对锁获取的中断 then InterruptedException is thrown and the current thread
's interrupted status is cleared.
//则将抛出 InterruptedException,并清除当前线程的已中断状态。

boolean tryLock()
Acquires the lock only if it is free at the time of invocation.
//仅在调用时锁为空闲状态才获取该锁。 Acquires the lock
if it is available and returns immediately with the value true.
//如果锁可用,则获取锁,并立即返回值 true。
If the lock is not available then this method will return immediately with the value false. //如果锁不可用,则此方法将立即返回值 false。 A typical usage idiom for this method would be: Lock lock = ...; if (lock.tryLock()) { try { // manipulate protected state } finally { lock.unlock(); } } else { // perform alternative actions } This usage ensures that the lock is unlocked if it was acquired, and doesn't try to unlock if the lock was not acquired.
//此用法可确保如果获取了锁,则会释放锁,如果未获取锁,则不会试图将其释放。 Returns: true if the lock was acquired and false otherwise

boolean tryLock(long time,TimeUnit unit) throws InterruptedException
Acquires the lock if it is free within the given waiting time and the current thread has not been interrupted.
//如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。 If the lock is available
this method returns immediately with the value true.
If the lock is not available then the current thread becomes disabled for thread scheduling purposes and lies dormant
until one of three things happens: //如果锁可用,则此方法将立即返回值 true。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下三种情况之一前,该线程将一直处于休眠状态: The lock is acquired by the current thread; or Some other thread interrupts the current thread, and interruption of lock acquisition is supported; or The specified waiting time elapses If the lock is acquired then the value
true is returned. //锁由当前线程获得;或者 其他某个线程中断当前线程,并且支持对锁获取的中断;或者 已超过指定的等待时间 如果获得了锁,则返回值 true。 If the current thread: has its interrupted status set on entry to this method; or is interrupted while acquiring the lock, and interruption of lock acquisition is supported, then InterruptedException is thrown and the current thread's interrupted status is cleared. If the specified waiting time elapses then the value false is returned. If the time is less than or equal to zero, the method will not wait at all.
//如果当前线程:在进入此方法时已经设置了该线程的中断状态;或者 在获取锁时被中断,并且支持对锁获取的中断,则将抛出 InterruptedException,并会清除当前线程的已中断状态。
//如果超过了指定的等待时间,则将返回值 false。如果 time 小于等于 0,该方法将完全不等待。
Returns:true if the lock was acquired and false if the waiting time elapsed before the lock was acquired
//如果获得了锁,则返回 true;如果在获取锁前超过了等待时间,则返回 false

package soarhu;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

class TestNum {
    final ReentrantLock lock = new ReentrantLock(true);
    private Condition condition = lock.newCondition();
    void test() {
        lock.lock();//lock()不支持锁中断
        try {
            System.out.println("lock begin "+Thread.currentThread().getName());
            for (int i = 0; i < Integer.MAX_VALUE/20; i++) {
                Math.random();
            }
            System.out.println("lock end "+Thread.currentThread().getName());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if( lock.isHeldByCurrentThread())
                lock.unlock();
        }
    }
}
public class Test{
    public static void main(String[] args) throws InterruptedException {
        TestNum t = new TestNum();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                t.test();
            }
        };
        Thread thread = new Thread(runnable);
        thread.setName("a");
        thread.start();
        Thread.sleep(500);
        Thread thread2 = new Thread(runnable);
        thread2.setName("b");
        thread2.start();
        thread2.interrupt();//发出中断指令
    }
}

输出结果:正常运行完毕,没有收到异常信息。

lock begin a
lock end a
lock begin b
lock end b

如果代码改为如下:那么会发生异常:

class TestNum {
    final ReentrantLock lock = new ReentrantLock(true);
    private Condition condition = lock.newCondition();
    void test() {
        try {
            lock.lockInterruptibly();
            System.out.println("lock begin "+Thread.currentThread().getName());
            for (int i = 0; i < Integer.MAX_VALUE/20; i++) {
                Math.random();
            }
            System.out.println("lock end "+Thread.currentThread().getName());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if( lock.isHeldByCurrentThread())
                lock.unlock();
        }
    }
}

输出结果:

lock begin a
java.lang.InterruptedException
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1220)
    at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
    at soarhu.TestNum.test(Test.java:12)
    at soarhu.Test$1.run(Test.java:32)
    at java.lang.Thread.run(Thread.java:745)
lock end a

Process finished with exit code 0

输出结果:可中断的异常能够接收到异常信息

class TestNum {
    final ReentrantLock lock = new ReentrantLock(true);
    private Condition condition = lock.newCondition();
    void test() {
        if(lock.tryLock()){
            try {
                System.out.println("lock begin "+Thread.currentThread().getName());
                for (int i = 0; i < Integer.MAX_VALUE/20; i++) {
                    Math.random();
                }
                System.out.println("lock end "+Thread.currentThread().getName());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if( lock.isHeldByCurrentThread())
                    lock.unlock();
            }
        }else{
            System.out.println("can't get lock,return as fast "+Thread.currentThread().getName());
        }
    }
}

输出结果:

lock begin a
can't get lock,return as fast b
lock end a

Process finished with exit code 0

分析:线程a获取锁时,锁是空闲的,那么会立即返回true.当线程b尝试获取锁时,发现锁正忙,那么就立即返回false。此锁是不可中断锁。

package soarhu;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

class TestNum {
    final ReentrantLock lock = new ReentrantLock(true);
    private Condition condition = lock.newCondition();
    void test() {

            try {
                if(lock.tryLock(3000, TimeUnit.MILLISECONDS)){
   
   //1
                    System.out.println("lock begin "+Thread.currentThread().getName());
                    for (int i = 0; i < Integer.MAX_VALUE/20; i++) {
                        Math.random();
                    }
                    System.out.println("lock end "+Thread.currentThread().getName());
                }else{
                    System.out.println("can't get lock,return as fast "+Thread.currentThread().getName());//2
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if( lock.isHeldByCurrentThread())
                    lock.unlock();
            }

    }
}
public class Test{
    public static void main(String[] args) throws InterruptedException {
        TestNum t = new TestNum();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                t.test();
            }
        };
        Thread thread = new Thread(runnable);
        thread.setName("a");
        thread.start();
        //Thread.sleep(500);
        Thread thread2 = new Thread(runnable);
        thread2.setName("b");
        thread2.start();
        //thread2.interrupt(); //3
    }
}

输出结果:

lock begin a
lock end a
lock begin b
lock end b

分析:在第一行等待时间为3秒钟内,线程a获取到了锁,执行。然后b线程也尝试在3秒内获取锁,但在此时间内,a线程已运行完毕,b线程能正常获取锁。如果第一行改为  if(lock.tryLock(3, TimeUnit.MILLISECONDS)){
 那么输出结果为:

lock begin a
can't get lock,return as fast b
lock end a

Process finished with exit code 0

3毫秒的时间内a线程获取锁并正在执行任务,此时b线程进来锁正忙,于是立即被返回。如果把第三行注释取消掉,那么运行程序会抛出异常

输出结果:

lock begin a
java.lang.InterruptedException
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireNanos(AbstractQueuedSynchronizer.java:1245)
    at java.util.concurrent.locks.ReentrantLock.tryLock(ReentrantLock.java:442)
    at soarhu.TestNum.test(Test.java:13)
    at soarhu.Test$1.run(Test.java:37)
    at java.lang.Thread.run(Thread.java:745)
lock end a

Process finished with exit code 0

可见 public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException 具有前面三种锁的能力。

转载于:https://www.cnblogs.com/soar-hu/p/6732252.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/108565.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • php header 404写法 php header函数用法

    php header 404写法 php header函数用法header("HTTP/1.1404NotFound");exit;

    2022年7月1日
    22
  • python可变参数调用函数的问题

    python可变参数调用函数的问题

    2021年12月30日
    50
  • 模拟量差分和单端(iou计算方法)

    一.计算IOU人工修正后的每一个框与算法输出的所有框去计算IOU,取出IOU大于0.9的算法输出框defcompute_IOU(algrim_bboxs,fix_bboxs):#print(‘algrim_bboxs:’,algrim_bboxs)#print(‘fix_bboxs:’,fix_bboxs)fori,fix_bboxinen…

    2022年4月15日
    51
  • linux查看日志方法

    linux查看日志方法linux日志查看tail、head、cat、tac、sed、less、echo1、命令格式:tail[必要参数][选择参数][文件]-f循环读取-q不显示处理信息-v显示详细的处理信息-c<数目>显示的字节数-n<行数>显示行数-q,–quiet,–silent从不输出给出文件名的首部-s,–sleep-interval=S与-f合用,表示在每次反复的间隔休眠S秒tail-n…

    2022年6月23日
    32
  • 尚硅谷java培训几个月,经验分享

    尚硅谷java培训几个月,经验分享Java代码是怎么运行的?Java的基本类型Java虚拟机是如何加载Java类的JVM是如何执行方法调用的?(上)JVM是如何执行方法调用的?(下)JVM是如何处理异常的?JVM是如何实现反射的?JVM是怎么实现invokedynamic的?(上)JVM是怎么实现invokedynamic的?(下)Java对象的内存布局垃圾回收(上)垃圾回收(下)Java内存模型Java虚拟机是怎么实现synchronized的?Java语法糖与Java编译器16

    2022年7月8日
    20
  • Web服务器配置(服务器配置信息怎么查)

    课程名称服务器配置与管理实验成绩 实验名称Web服务器配置学号 姓名;指导老师-龚蕾 班级 日期 实验目的:1.掌握liunx系统的基本命令2 掌握Web服务器配置的基本原理3.掌握Apache服务器的安装与配制方法和客户端的测试方法实验平台:  云平台一、  实验内容配置Web服务器,可以从客户端访问服务器,打开网页。二、  服务器端设置1、    配置DNS服务器,要求能够解析域名。2、   …

    2022年4月14日
    46

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号