`

Java多线程之Lock的使用 .

 
阅读更多
01.import java.util.concurrent.ExecutorService;  
02.import java.util.concurrent.Executors;  
03.import java.util.concurrent.Future;  
04.import java.util.concurrent.locks.Lock;  
05.import java.util.concurrent.locks.ReadWriteLock;  
06.import java.util.concurrent.locks.ReentrantLock;  
07.import java.util.concurrent.locks.ReentrantReadWriteLock;  
08.  
09./** 
10. * Lockers 
11. * 在多线程编程里面一个重要的概念是锁定,如果一个资源是多个线程共享的,为了保证数据的完整性, 
12. * 在进行事务性操作时需要将共享资源锁定,这样可以保证在做事务性操作时只有一个线程能对资源进行操作, 
13. * 从而保证数据的完整性。在5.0以前,锁定的功能是由Synchronized关键字来实现的。 
14. */  
15.public class Lockers {  
16.      
17.    /** 
18.     * 测试Lock的使用。在方法中使用Lock,可以避免使用Synchronized关键字。 
19.     */  
20.    public static class LockTest {  
21.  
22.        Lock lock = new ReentrantLock();// 锁   
23.        double value = 0d; // 值   
24.        int addtimes = 0;  
25.  
26.        /** 
27.         * 增加value的值,该方法的操作分为2步,而且相互依赖,必须实现在一个事务中 
28.         * 所以该方法必须同步,以前的做法是在方法声明中使用Synchronized关键字。 
29.         */  
30.        public void addValue(double v) {  
31.            lock.lock();// 取得锁   
32.            System.out.println("LockTest to addValue: " + v + "   "  
33.                    + System.currentTimeMillis());  
34.            try {  
35.                Thread.sleep(1000);  
36.            } catch (InterruptedException e) {  
37.            }  
38.            this.value += v;  
39.            this.addtimes++;  
40.            lock.unlock();// 释放锁   
41.        }  
42.  
43.        public double getValue() {  
44.            return this.value;  
45.        }  
46.    }  
47.    public static void testLockTest() throws Exception{  
48.        final LockTest lockTest = new LockTest();  
49.        // 新建任务1,调用lockTest的addValue方法   
50.        Runnable task1 = new Runnable(){  
51.            public void run(){  
52.                lockTest.addValue(55.55);  
53.            }  
54.        };  
55.        // 新建任务2,调用lockTest的getValue方法   
56.        Runnable task2 = new Runnable(){  
57.            public void run(){  
58.                System.out.println("value: " + lockTest.getValue());  
59.            }  
60.        };  
61.        // 新建任务执行服务   
62.        ExecutorService cachedService = Executors.newCachedThreadPool();  
63.        Future future = null;  
64.        // 同时执行任务1三次,由于addValue方法使用了锁机制,所以,实质上会顺序执行   
65.        for (int i=0; i<3; i++){  
66.            future = cachedService.submit(task1);  
67.        }  
68.        // 等待最后一个任务1被执行完   
69.        future.get();  
70.        // 再执行任务2,输出结果   
71.        future = cachedService.submit(task2);  
72.        // 等待任务2执行完后,关闭任务执行服务   
73.        future.get();  
74.        cachedService.shutdownNow();  
75.    }  
76.      
77.    /** 
78.     * ReadWriteLock内置两个Lock,一个是读的Lock,一个是写的Lock。 
79.     * 多个线程可同时得到读的Lock,但只有一个线程能得到写的Lock, 
80.     * 而且写的Lock被锁定后,任何线程都不能得到Lock。ReadWriteLock提供的方法有: 
81.     * readLock(): 返回一个读的lock  
82.     * writeLock(): 返回一个写的lock, 此lock是排他的。 
83.     * ReadWriteLockTest很适合处理类似文件的读写操作。 
84.     * 读的时候可以同时读,但不能写;写的时候既不能同时写也不能读。 
85.     */  
86.    public static class ReadWriteLockTest{  
87.        // 锁   
88.        ReadWriteLock lock = new ReentrantReadWriteLock();  
89.        // 值   
90.        double value = 0d;  
91.        int addtimes = 0;  
92.          
93.        /** 
94.         * 增加value的值,不允许多个线程同时进入该方法 
95.         */  
96.        public void addValue(double v) {  
97.            // 得到writeLock并锁定   
98.            Lock writeLock = lock.writeLock();  
99.            writeLock.lock();  
100.            System.out.println("ReadWriteLockTest to addValue: " + v + "   "  
101.                    + System.currentTimeMillis());  
102.            try {  
103.                Thread.sleep(1000);  
104.            } catch (InterruptedException e) {  
105.            }  
106.            try {  
107.                // 做写的工作   
108.                this.value += v;  
109.                this.addtimes++;  
110.            } finally {  
111.                // 释放writeLock锁   
112.                writeLock.unlock();  
113.            }  
114.        }  
115.        /** 
116.         * 获得信息。当有线程在调用addValue方法时,getInfo得到的信息可能是不正确的。 
117.         * 所以,也必须保证该方法在被调用时,没有方法在调用addValue方法。 
118.         */  
119.        public String getInfo() {  
120.            // 得到readLock并锁定   
121.            Lock readLock = lock.readLock();  
122.            readLock.lock();  
123.            System.out.println("ReadWriteLockTest to getInfo   "  
124.                    + System.currentTimeMillis());  
125.            try {  
126.                Thread.sleep(1000);  
127.            } catch (InterruptedException e) {  
128.            }  
129.            try {  
130.                // 做读的工作   
131.                return this.value + " : " + this.addtimes;  
132.            } finally {  
133.                // 释放readLock   
134.                readLock.unlock();  
135.            }  
136.        }  
137.    }  
138.      
139.    public static void testReadWriteLockTest() throws Exception{  
140.        final ReadWriteLockTest readWriteLockTest = new ReadWriteLockTest();  
141.        // 新建任务1,调用lockTest的addValue方法   
142.        Runnable task_1 = new Runnable(){  
143.            public void run(){  
144.                readWriteLockTest.addValue(55.55);  
145.            }  
146.        };  
147.        // 新建任务2,调用lockTest的getValue方法   
148.        Runnable task_2 = new Runnable(){  
149.            public void run(){  
150.                System.out.println("info: " + readWriteLockTest.getInfo());  
151.            }  
152.        };  
153.        // 新建任务执行服务   
154.        ExecutorService cachedService_1 = Executors.newCachedThreadPool();  
155.        Future future_1 = null;  
156.        // 同时执行5个任务,其中前2个任务是task_1,后两个任务是task_2   
157.        for (int i=0; i<2; i++){  
158.            future_1 = cachedService_1.submit(task_1);  
159.        }  
160.        for (int i=0; i<2; i++){  
161.            future_1 = cachedService_1.submit(task_2);  
162.        }  
163.        // 最后一个任务是task_1   
164.        future_1 = cachedService_1.submit(task_1);  
165.        // 这5个任务的执行顺序应该是:   
166.        // 第一个task_1先执行,第二个task_1再执行;这是因为不能同时写,所以必须等。   
167.        // 然后2个task_2同时执行;这是因为在写的时候,就不能读,所以都等待写结束,   
168.        // 又因为可以同时读,所以它们同时执行   
169.        // 最后一个task_1再执行。这是因为在读的时候,也不能写,所以必须等待读结束后,才能写。   
170.          
171.        // 等待最后一个task_2被执行完   
172.        future_1.get();  
173.        cachedService_1.shutdownNow();  
174.    }  
175.  
176.    public static void main(String[] args) throws Exception{  
177.        Lockers.testLockTest();  
178.        System.out.println("---------------------");  
179.        Lockers.testReadWriteLockTest();  
180.    }  
181.}  
分享到:
评论

相关推荐

    多线程系列相关的技术要点

    1. Java多线程学习(一)Java多线程入门 2. Java多线程学习(二)synchronized...7. Java多线程学习(六)Lock锁的使用 8. Java多线程学习(七)并发编程中一些问题 9. Java多线程学习(八)线程池与Executor 框架

    java多线程安全性基础介绍.pptx

    java多线程安全性基础介绍 线程安全 正确性 什么是线程安全性 原子性 竞态条件 i++ 读i ++ 值写回i 可见性 JMM 由于cpu和内存加载速度的差距,在两者之间增加了多级缓存导致,内存并不能直接对cpu可见。 ...

    多线程,高并发.pdf

    1. stop() 和 suspend() 方法为何不推荐使用? 2. sleep() 和 wait() 有什么区别? 3. 同步和异步有何异同,...5. 简述 synchronized 和 java.util.concurrent.locks.Lock 的异同? 6. 概括的解释下线程的几种可用状态。

    java模拟多线程买票问题.docx

    多线程买票是java中的一个经典案例,其主要思想无非包括2点,synchronized和锁,两者中,前者实现同步,后者为同步的线程提供锁,从而实现多个线程共享同一份资源时候,能够同步进行; 经典的方式是synchronized + 锁...

    Java多线程源码笔记.pdf

    1.什么是多线程 2.Thread类解析 3.使用多线程需要注意的问题 4.synchronized锁和lock锁 5.AQS 6.ReentrantLock和ReentrantReadWriteLock 7.线程池 8.死锁 9.线程常用的工具栏 10.Atomic 11.ThreadLocal

    concurrent 多线程 教材

    07 使用JAVA建立稳定的多线程服务器 (3) 08 线程池的介绍及简单实现 09 Java实时多任务调度过程中的安全监控设计 (3) 10 不要重新分配被锁定对象的对象引用 11 以全局的固定顺序获取多个锁来避免死锁 12 Java...

    Lock总结.doc

    java多线程之lock。 Lock的基本用法如下,为了防止异常退出时没有释放锁,一般都在拿到锁后立马try,try住所有临界区的代码,然后finally释放锁。

    java多线程编程_java多线程_

    1.讲解了Java多线程的基础, 包括Thread类的核心API的使用。2.讲解了在多线程中对并发访问的控制, 主要就是synchronized的使用, 由于此关键字在使用上非常灵活, 所以书中用了很多案例来介绍此关键字的使用, 为...

    计算机后端-Java-Java核心基础-第20章 多线程 13. Lock锁方式解决线程安全问题.avi

    计算机后端-Java-Java核心基础-第20章 多线程 13. Lock锁方式解决线程安全问题.avi

    java多线程设计模式详解(PDF及源码)

    (注意,本资源附带书中源代码可供参考) 多线程与并发处理是程序设计好坏优劣的重要课题,本书通过浅显易懂的文字与实例来介绍Java线程相关的设计模式概念,并且通过实际的Java程序范例和 UML图示来一一解说,书中...

    java多线程死锁预防机制研究

    java多线程死锁预防机制研究,java多线程死锁预防机制研究

    Java多线程编程 线程同步机制.docx

    线程安全问题的产生是因为多个线程并发访问共享数据造成的,如果能将多个线程对共享数据的并发访问改为串行访问,即一个共享数据同一时刻只能被一个线程访问,就可以避免线程安全问题。锁正是基于这种思路实现的一种...

    Java毕业设计-Java多线程与线程安全实践-基于Http协议的断点续传.rar

    Java多线程与线程安全实践-基于Http协议的断点续传.rar 是一个Java毕业设计项目,旨在探讨如何在Java中实现多线程和线程安全,以及如何基于Http协议实现断点续传功能。该项目提供了一个完整的源代码包,可以作为学习...

    java核心知识点整理.pdf

    25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................

    Java学习源码Java多线程的代码

    在char01包里放置Java多线程基本知识的代码。内容如下: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 在char02包里放置了Java对变量和对象并发访问的知识的代码...

    Linux多线程服务端编程:使用muduo C++网络库

    《Linux多线程服务端编程:使用muduo C++网络库》主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread。...

    python多线程DAY04.txt

    Lock lock.acquire() lock.release() 4. 什么是线程 threading Thread() t.start() t.join() t.name t.getName t.setName t.daemon t.is_alive() 5. 自定义线程类 继承 Thread 重写 run 6. 线程...

    Java多线程中Lock锁的使用总结

    主要介绍了Java多线程中Lock锁的使用总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    java多线程实现生产者和消费者

    java多线程实现生产者和消费者 ,4种实现方式,分别为synchronizated,condition和lock,信号量,阻塞队列

Global site tag (gtag.js) - Google Analytics