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


相关推荐

  • android 壁纸尺寸,常见手机壁纸的尺寸是多少

    android 壁纸尺寸,常见手机壁纸的尺寸是多少不同的手机屏幕分辨率不一样,对应的屏幕壁纸尺寸大小也不一样,这里改图宝整理了一些市面上常见的手机型号的壁纸尺寸给大家(单位都为像素):苹果AppleiPhone6:872×1634;iPhone6Plus::2706×2706;iPhone5s:640×1136;iPhone5:640×1136;iPhone8:1334×750;iPhoneX:2436x1125iP…

    2022年6月20日
    137
  • C语言关键字之voliate

    C语言关键字之voliateC语言关键字之voliatevoliate的作用是作为指令关键字,确保本条指令不会因为编译器的优化而省略,而且要求每次从内存中直接读取值当使用voliate声明变量值时,系统总是重新从它所在的内存读取数据,直接访问变量地址,而编译器对于访问该变量时也不再进行优化voliate关键字影响编译器的结果,用voliate声明的变量表示该变量随时可能发生变化(因为编译器优化时可能将其放入寄存器中),与…

    2022年5月6日
    65
  • 10分钟让你掌握Linux常用命令(+1万+++收藏)

    10分钟让你掌握Linux常用命令(+1万+++收藏)1、目录操作。2、文件操作。3、文件内容操作。4、压缩和解压缩。5、日志查看。6、Linux下文件的详细信息。7、常用的docker容器的命令。8、其他命令。

    2022年6月14日
    36
  • MOS管功率放大器电路图与原理图文及其解析[通俗易懂]

    MOS管功率放大器电路图与原理图文及其解析[通俗易懂]放大器电路的分类本文介绍MOS管功率放大器电路图,先来看看放大器电路的分类,按功率放大器电路中晶体管导通时间的不同可分:甲类功率放大器电路、乙类功率放大器电路和丙类功率放大器电路。甲类功率放大器电路,在信号全范围内均导通,非线性失真小,但输出功率和效率低,因此低频功率放大器电路中主要用乙类或甲乙类功率放大电路。功率放大器是根据信号的导通角分为A、B、AB、C和D类,我国亦称为甲、乙、甲乙、丙和丁类。功率放大器电路的特殊问题(1)放大器电路的功率功率放大器电路的任务是推动负载,因此功率放大电路的重

    2022年6月3日
    74
  • iframe跨域调用js_ajax跨域访问

    iframe跨域调用js_ajax跨域访问概述本地同一浏览器访问本地HTML文件和访问服务器端HTML文件,本地Iframe没有自适应高度,而服务器端的Ifrane自适应了高度。1.问题重现:Chrome版本41.0.2272.101(64-bit)OS:Win8.1Chrome访问服务器端HTML文件呈现的结果Chrome访问本地HTML文件呈现的结果本地访问的HTML文件Iframe没有根据Iframe里面的页面类容自适应高度2…

    2022年9月28日
    0
  • linux vim怎么退出编辑模式_shell退出vi编辑器

    linux vim怎么退出编辑模式_shell退出vi编辑器用的命令是:ctrl+Rvi编辑器中有三种状态模式1.命令模式2.输入模式3.末行模式三种模式间的相互转换vi编辑器的启动与退出直接进入编辑环境$vi进入编辑环境并打开(新建)文件$vimyfile退出vi编辑环境输入末行命令放弃对文件的修改,并退出编辑器:q!文件保存与另存为保存文件保存对vi编辑器中已打开文件的修改:w另存为文件将vi编辑器中的内容另存为指定文件名:wmyfile退…

    2022年9月30日
    0

发表回复

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

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