文档章节

Java并发编程初级篇(十三):使用锁来实现同步机制

阿拉德大陆的魔法师
 阿拉德大陆的魔法师
发布于 2016/11/25 10:41
字数 868
阅读 52
收藏 0

Java API除了提供synchronized关键字实现同步机制外,还提供了Lock接口以及它的实现类ReentrantLock。Lock接口除了能够实现同步机制外,还提供了一个tryLock()方法的实现。这个方法会试图获得锁,如果锁已经被其他线程获取,它将返回false并继续往下执行代码。

你会发现使用Lock接口更加灵活,因为synchronized同步代码当A线程进入后,其他视图访问同步代码的线程都会被挂起直到A线程执行完毕。而Lock接口允许你通过编码的方式来决定是否实现同步代码,并且可以使用tryLock()检测锁是否被其他线程获取,如果其他线程拥有锁,那么这个线程可以选择跳过同步代码继续向下执行。

看一个示例:

我们模拟一个打印队列PrintQueue,在这个类中,我们定义一个锁new ReentrantLock(),使用一个随机数等待时间模拟打印过程,在打印开始时加锁,打印结束后在finally块中释放锁,释放锁这一步是必不可少的,不然这个锁一直会被锁定,其他线程就无法获得这个锁,就会造成了死锁。

public class PrintQueue {
    private final Lock queueLock = new ReentrantLock();

    public void printJob(Object document) {
        try {
            queueLock.lock();

            long duration = (long)(Math.random() * 10000);
            System.out.println(Thread.currentThread().getName() +
                    " PrintQueue: print a job during " + (duration/1000) + " seconds");

            Thread.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            queueLock.unlock();
        }
    }
}

创建一个工作线程,调用打印对列类执行打印操作。

public class Job implements Runnable{
    private PrintQueue printQueue;

    public Job(PrintQueue printQueue) {
        this.printQueue = printQueue;
    }

    @Override
    public void run() {
        System.out.printf("%s: Going to print a document.\n", Thread.currentThread().getName());
        printQueue.printJob(new Object());
        System.out.printf("%s: The document has been printed.\n", Thread.currentThread().getName());
    }
}

创建主方法类,新建打印队列并启动10个线程来执行打印操作。

public class Job implements Runnable{
    private PrintQueue printQueue;

    public Job(PrintQueue printQueue) {
        this.printQueue = printQueue;
    }

    @Override
    public void run() {
        System.out.printf("%s: Going to print a document.\n", Thread.currentThread().getName());
        printQueue.printJob(new Object());
        System.out.printf("%s: The document has been printed.\n", Thread.currentThread().getName());
    }
}

查看控制台日志,发现10个打印线程几乎同时启动,但每次只有一个线程能够获取锁并执行打印操作,其他线程等待上一个线程执行完毕释放锁后继续竞争锁,获取锁的线程继续执行,其他线程继续等待,直到所有线程执行完毕。

Thread-0: Going to print a document.
Thread-0 PrintQueue: print a job during 4 seconds
Thread-9: Going to print a document.
Thread-8: Going to print a document.
Thread-7: Going to print a document.
Thread-6: Going to print a document.
Thread-5: Going to print a document.
Thread-4: Going to print a document.
Thread-3: Going to print a document.
Thread-2: Going to print a document.
Thread-1: Going to print a document.
Thread-0: The document has been printed.
Thread-9 PrintQueue: print a job during 2 seconds
Thread-9: The document has been printed.
Thread-8 PrintQueue: print a job during 2 seconds
Thread-8: The document has been printed.
Thread-7 PrintQueue: print a job during 3 seconds
Thread-7: The document has been printed.
Thread-6 PrintQueue: print a job during 8 seconds
Thread-6: The document has been printed.
Thread-5 PrintQueue: print a job during 4 seconds
Thread-5: The document has been printed.
Thread-4 PrintQueue: print a job during 9 seconds
Thread-4: The document has been printed.
Thread-3 PrintQueue: print a job during 8 seconds
Thread-3: The document has been printed.
Thread-2 PrintQueue: print a job during 7 seconds
Thread-2: The document has been printed.
Thread-1 PrintQueue: print a job during 6 seconds
Thread-1: The document has been printed.

 

© 著作权归作者所有

共有 人打赏支持
阿拉德大陆的魔法师
粉丝 24
博文 91
码字总数 83019
作品 0
西城
程序员
读书笔记之《Java并发编程的艺术》-并发编程容器和框架(重要)

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
1
读书笔记之《Java并发编程的艺术》-并发编程基础

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
8
读书笔记之《Java并发编程的艺术》-线程池和Executor的子孙们

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
1
跳槽时,这些Java面试题99%会被问到

我在 Oracle 已经工作了近 7 年,面试过从初级到非常资深的Java工程师,且由于 Java 组工作任务的特点,我非常注重面试者的计算机科学基础和编程语言的理解深度,可以不要求面试者非要精通 ...

Java小铺
08/15
0
0
【死磕Java并发】—– 死磕 Java 并发精品合集

【死磕 Java 并发】系列是 LZ 在 2017 年写的第一个死磕系列,一直没有做一个合集,这篇博客则是将整个系列做一个概览。 先来一个总览图: 【高清图,请关注“Java技术驿站”公众号,回复:脑...

chenssy
07/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

TypeScript基础入门之JSX(二)

转发 TypeScript基础入门之JSX(二) 属性类型检查 键入检查属性的第一步是确定元素属性类型。 内在元素和基于价值的元素之间略有不同。 对于内部元素,它是JSX.IntrinsicElements上的属性类型...

durban
20分钟前
0
0
AVA中CAS-ABA的问题解决方案AtomicStampedReference

了解CAS(Compare-And-Swap) CAS即对比交换,它在保证数据原子性的前提下尽可能的减少了锁的使用,很多编程语言或者系统实现上都大量的使用了CAS。 JAVA中CAS的实现 JAVA中的cas主要使用的是...

码代码的小司机
22分钟前
0
0
Android JNI开发系列(十三) JNI异常处理

JNI 异常处理 JNI异常与JAVA处理异常的区别 JAVA 有异常处理机制,而JNI没有 如果JAVA中异常没有捕获,后面的代码不会执行,JNI会执行 JAVA编译时的异常,是在方法显示的声明了某一个异常,编...

蔡小鹏
35分钟前
2
0
简单介绍Java 的JAR包、EAR包、WAR包区别

WAR包 WAR(Web Archive file)网络应用程序文件,是与平台无关的文件格式,它允许将许多文件组合成一个压缩文件。War专用于Web方面。大部分的JAVA WEB工程,都是打成WAR包进行发布的。 War是...

Linux就该这么学
今天
1
0
Qt那些事0.0.7

在帮助文档(Overview - QML and C++ Integration)中随缘遇到一张图,是关于C++对象与QML整合介绍的,值得标记下来,虽然大部分功能也有所涉猎,但是还是留个记号,万一哪天我失忆了还想写Q...

Ev4n
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部