文档章节

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.

 

© 著作权归作者所有

共有 人打赏支持
阿拉德大陆的魔法师
粉丝 22
博文 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小铺
昨天
0
0
[Java 并发编程] 集合框架之 同步容器类 & 并发容器类

吾生也有涯,而知也无涯。———《庄子》 通过上一篇文章,我们已经知道设计一个线程安全类的原则和步骤,以及在设计过程中我们应当注意的细节。实际上,Java 的集合库包含了线程安全集合和非...

seaicelin
05/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

git +STS使用问题解决一

1. 2.点以一个pull就是更新代码 3.synchronize workSpace 同步代码,同SVN一致

森火
4分钟前
0
0
powerBi odbc 连接impala 实现自助分析

配置Impala以使用ODBC 可以将第三方产品设计为使用ODBC与Impala集成。为获得最佳体验,请确保支持您打算使用的任何第三方产品。验证支持包括检查Impala,ODBC,操作系统和第三方产品的版本是...

hblt-j
8分钟前
0
0
Purism FAQ

<font size="37" color="#006248" face="幼圆"> <p align="center"> Purism FAQ </p> </font> 原文:https://puri.sm/faq/ 原作者:Purism Team 翻译者:冰焰火灵X 1079092922@qq.com 文章许......

ICE冰焰火灵X
24分钟前
0
0
nginx+webdav

1、配置Nginx以支持WebDav: Webdav是nginx一个组件,默认编译nginx时是没有安装这个组件的。 如果跟应用公用一个nginx,需要重新编译安装nginx,重新安装前需要备份好原来的nginx.conf。 1....

yaukie
29分钟前
0
0
spring 事件

ContextRefreshedEvent Event raised when an {@code ApplicationContext} gets initialized or refreshed. ContextClosedEvent Event raised when an {@code ApplicationContext} gets clos......

Canaan_
41分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部