[Java] Java多线程编程中的lock使用代码详解 →→→→→进入此内容的聊天室

来自 , 2019-03-27, 写在 Java, 查看 134 次.
URL http://www.code666.cn/view/8d6a06b2
  1. import java.util.concurrent.ExecutorService;
  2. import java.util.concurrent.Executors;
  3. import java.util.concurrent.Future;
  4. import java.util.concurrent.locks.Lock;
  5. import java.util.concurrent.locks.ReadWriteLock;
  6. import java.util.concurrent.locks.ReentrantLock;
  7. import java.util.concurrent.locks.ReentrantReadWriteLock;
  8.  
  9. /**
  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. }
  182. //java/6132

回复 "Java多线程编程中的lock使用代码详解"

这儿你可以回复上面这条便签

captcha