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


相关推荐

  • 5000张高清壁纸大图(手机用),用Python在法律的边缘又试探了一把

    5000张高清壁纸大图(手机用),用Python在法律的边缘又试探了一把一辈子的手机壁纸都够用了

    2022年6月3日
    29
  • Lucene(8_2_0)核心API学习 之 TokenStream(一)「建议收藏」

    Lucene(8_2_0)核心API学习 之 TokenStream(一)「建议收藏」一、继承org.apache.lucene.analysis.TokenStreamentendsorg.apache.lucene.util.AttributeSource二、详情TokenStream是一个抽象类,是一系列Token的枚举,这里的Token有两个来源,一是Document的Fields,一是查询语句Query; 这是一个抽象类,有两个具体子类:Tokeni…

    2022年7月22日
    15
  • OPC协议_opc协议端口号

    OPC协议_opc协议端口号当然,OPCUA组件也可以在Unix操作系统的信息技术(IT)系统中使用,诸如:Solaris、HPUX、AIX、Linux等,可以是企业资源计划(ERP)系统,可以是生产计划(MES)和监控软件(SCADA),还可以是电子商务应用。OPCUA接口协议包含了之前的A&E,DA,OPCXMLDAorHDA,只使用一个地址空间就能访问之前所有的对象,而且不受WINDOWS平台限制,因为它是从传输层Scoket以上来定义的,这点后面会提到,导致了灵活性和安全性比之前的OPC都提升了。……

    2025年5月26日
    0
  • 什么是下折?

    什么是下折?所谓下折,是指当分级基金B份额的净值下跌到某个价格(比如0.25元)时,为了保护A份额持有人利益,基金公司按照合同约定对分级基金进行向下折算,折算完成后,A份额和B份额的净值重新回归初始净值1元,A

    2022年7月2日
    28
  • IntelliJ Idea 2017 注册码 免费激活方法「建议收藏」

    IntelliJ Idea 2017 注册码 免费激活方法「建议收藏」!!!补充版本信息,博友反馈17.3版本之后的不能用。注:如果为2017.3之后的版本,参考评论中23楼提供的博文,最近比较忙,没能补充新版本激活方法。谢谢23楼博友!!!可使用以下两种

    2022年7月3日
    120
  • Autoconf使用「建议收藏」

    Autoconf使用「建议收藏」 AutoconfCreatingAutomaticConfigurationScriptsEdition2.13,forAutoconfversion2.13December1998byDavidMacKenzieandBenElliston  目录介绍创建configure脚本编写`configur

    2022年5月4日
    36

发表回复

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

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