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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 前端vue生成二维码带logo并且可以点击下载保存_vue实现扫描二维码

    前端vue生成二维码带logo并且可以点击下载保存_vue实现扫描二维码下载插件:npminstallvue-qr<template><divclass=”sg-qrcode”><vue-qr:text=”qrcodeText”:correctLevel=”3″:size=”250″:margin=”10″colorDark=”#000″colorLight=”white”backgroundColor=”w…

    2022年10月3日
    1
  • 一文搞懂│php 中的 DI 依赖注入「建议收藏」

    一文搞懂│php 中的 DI 依赖注入「建议收藏」学好依赖注入,让编程更简单

    2022年8月16日
    4
  • FPN网络详解

    FPN网络详解特征图金字塔网络FPN(FeaturePyramidNetworks)是2017年提出的一种网络,FPN主要解决的是物体检测中的多尺度问题,通过简单的网络连接改变,在基本不增加原有模型计算量的情况下,大幅度提升了小物体检测的性能。低层的特征语义信息比较少,但是目标位置准确;高层的特征语义信息比较丰富,但是目标位置比较粗略。另外虽然也有些算法采用多尺度特征融合的方式,但是一般是采用融合后的特…

    2022年6月12日
    213
  • 反掩码有什么作用?通配符掩码有什么作用?

    反掩码有什么作用?通配符掩码有什么作用?反掩码是指路由器使用的通配符掩码与源或目标地址相匹配,与子网掩码正好相反。就像子网掩码告诉路由器IP地址中哪个属于网络号一样,通配符掩码告诉路由器,为了判断匹配,需要检查IP地址中有多少位。这种地址掩码可以使用两个32位的数字来确定IP地址的范围。这个非常方便,因为如果没有掩码,你必须在每个匹配的IP客户地址上添加一个单独的访问列表语句。它会导致许多额外的输入和路由器的额外处理过程。因此地址掩码非常有用。在子网掩码中,将一个掩码设置为1,表示IP地址对应的位置属于网络地址部分。相反,在访..

    2022年7月19日
    16
  • 查看服务器的外网地址[通俗易懂]

    查看服务器的外网地址[通俗易懂]服务器上执行以下命令:curlmembers.3322.org/dyndns/getip转载于:https://blog.51cto.com/zhenfen/2106824

    2022年5月1日
    145
  • MySQL的binlog日志详解

    binlog就是binarylog,二进制日志文件,这个文件记录了MySQL所有的DML操作。通过binlog日志我们可以做数据恢复,增量备份,主主复制和主从复制等等。对于开发者可能对binlog并不怎么关注,但是对于运维或者架构人员来讲是非常重要的。MySQL5.7这个版本默认是不开启binlog日志的,具体的开启方式可以查看https://blog.csdn.net/king_kgh…

    2022年4月5日
    43

发表回复

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

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