`

java 并发之(五.2)锁跟synchronized的区别

阅读更多

Lock是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题,我们拿Java线程(二)中的一个例子简单的实现一下和sychronized一样的效果,代码如下:

 

  1. public class LockTest {  
  2.     public static void main(String[] args) {  
  3.         final Outputter1 output = new Outputter1();  
  4.         new Thread() {  
  5.             public void run() {  
  6.                 output.output("zhangsan");  
  7.             };  
  8.         }.start();        
  9.         new Thread() {  
  10.             public void run() {  
  11.                 output.output("lisi");  
  12.             };  
  13.         }.start();  
  14.     }  
  15. }  
  16. class Outputter1 {  
  17.     private Lock lock = new ReentrantLock();// 锁对象  
  18.     public void output(String name) {  
  19.         // TODO 线程输出方法  
  20.         lock.lock();// 得到锁  
  21.         try {  
  22.             for(int i = 0; i < name.length(); i++) {  
  23.                 System.out.print(name.charAt(i));  
  24.             }  
  25.         } finally {  
  26.             lock.unlock();// 释放锁  
  27.         }  
  28.     }  
  29. }  

        这样就实现了和sychronized一样的同步效果,需要注意的是,用sychronized修饰的方法或者语句块在代码执行完之后锁自动释放,而是用Lock需要我们手动释放锁,所以为了保证锁最终被释放(发生异常情况),要把互斥区放在try内,释放锁放在finally内。

 

        如果说这就是Lock,那么它不能成为同步问题更完美的处理方式,下面要介绍的是读写锁(ReadWriteLock),我们会有一种需求,在对数据进行读写的时候,为了保证数据的一致性和完整性,需要读和写是互斥的,写和写是互斥的,但是读和读是不需要互斥的,这样读和读不互斥性能更高些,来看一下不考虑互斥情况的代码原型:

 

  1. public class ReadWriteLockTest {  
  2.     public static void main(String[] args) {  
  3.         final Data data = new Data();  
  4.         for (int i = 0; i < 3; i++) {  
  5.             new Thread(new Runnable() {  
  6.                 public void run() {  
  7.                     for (int j = 0; j < 5; j++) {  
  8.                         data.set(new Random().nextInt(30));  
  9.                     }  
  10.                 }  
  11.             }).start();  
  12.         }         
  13.         for (int i = 0; i < 3; i++) {  
  14.             new Thread(new Runnable() {  
  15.                 public void run() {  
  16.                     for (int j = 0; j < 5; j++) {  
  17.                         data.get();  
  18.                     }  
  19.                 }  
  20.             }).start();  
  21.         }  
  22.     }  
  23. }  
  24. class Data {      
  25.     private int data;// 共享数据      
  26.     public void set(int data) {  
  27.         System.out.println(Thread.currentThread().getName() + "准备写入数据");  
  28.         try {  
  29.             Thread.sleep(20);  
  30.         } catch (InterruptedException e) {  
  31.             e.printStackTrace();  
  32.         }  
  33.         this.data = data;  
  34.         System.out.println(Thread.currentThread().getName() + "写入" + this.data);  
  35.     }     
  36.     public void get() {  
  37.         System.out.println(Thread.currentThread().getName() + "准备读取数据");  
  38.         try {  
  39.             Thread.sleep(20);  
  40.         } catch (InterruptedException e) {  
  41.             e.printStackTrace();  
  42.         }  
  43.         System.out.println(Thread.currentThread().getName() + "读取" + this.data);  
  44.     }  
  45. }  

        部分输出结果:

 

 

  1. Thread-1准备写入数据  
  2. Thread-3准备读取数据  
  3. Thread-2准备写入数据  
  4. Thread-0准备写入数据  
  5. Thread-4准备读取数据  
  6. Thread-5准备读取数据  
  7. Thread-2写入12  
  8. Thread-4读取12  
  9. Thread-5读取5  
  10. Thread-1写入12  

        我们要实现写入和写入互斥,读取和写入互斥,读取和读取互斥,在set和get方法加入sychronized修饰符:

 

 

  1. public synchronized void set(int data) {...}      
  2. public synchronized void get() {...}  

        部分输出结果:

  1. Thread-0准备写入数据  
  2. Thread-0写入9  
  3. Thread-5准备读取数据  
  4. Thread-5读取9  
  5. Thread-5准备读取数据  
  6. Thread-5读取9  
  7. Thread-5准备读取数据  
  8. Thread-5读取9  
  9. Thread-5准备读取数据  
  10. Thread-5读取9  

        我们发现,虽然写入和写入互斥了,读取和写入也互斥了,但是读取和读取之间也互斥了,不能并发执行,效率较低,用读写锁实现代码如下:

 

 

  1. class Data {      
  2.     private int data;// 共享数据  
  3.     private ReadWriteLock rwl = new ReentrantReadWriteLock();     
  4.     public void set(int data) {  
  5.         rwl.writeLock().lock();// 取到写锁  
  6.         try {  
  7.             System.out.println(Thread.currentThread().getName() + "准备写入数据");  
  8.             try {  
  9.                 Thread.sleep(20);  
  10.             } catch (InterruptedException e) {  
  11.                 e.printStackTrace();  
  12.             }  
  13.             this.data = data;  
  14.             System.out.println(Thread.currentThread().getName() + "写入" + this.data);  
  15.         } finally {  
  16.             rwl.writeLock().unlock();// 释放写锁  
  17.         }  
  18.     }     
  19.     public void get() {  
  20.         rwl.readLock().lock();// 取到读锁  
  21.         try {  
  22.             System.out.println(Thread.currentThread().getName() + "准备读取数据");  
  23.             try {  
  24.                 Thread.sleep(20);  
  25.             } catch (InterruptedException e) {  
  26.                 e.printStackTrace();  
  27.             }  
  28.             System.out.println(Thread.currentThread().getName() + "读取" + this.data);  
  29.         } finally {  
  30.             rwl.readLock().unlock();// 释放读锁  
  31.         }  
  32.     }  
  33. }  

 

        部分输出结果:

 

  1. Thread-4准备读取数据  
  2. Thread-3准备读取数据  
  3. Thread-5准备读取数据  
  4. Thread-5读取18  
  5. Thread-4读取18  
  6. Thread-3读取18  
  7. Thread-2准备写入数据  
  8. Thread-2写入6  
  9. Thread-2准备写入数据  
  10. Thread-2写入10  
  11. Thread-1准备写入数据  
  12. Thread-1写入22  
  13. Thread-5准备读取数据  
分享到:
评论

相关推荐

    Java并发编程基础.pdf

    Java并发编程基础主要包括以下几个核心方面: 线程与线程状态:理解Java中线程的基本概念,包括线程的创建、启动、暂停、恢复和终止。熟悉线程的生命周期及其不同状态,如新建、就绪、运行、阻塞和死亡。 线程同步...

    java核心知识点整理.pdf

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

    Java 并发核心编程

    本文的主题是关于具有java语言风格的Thread、synchronized、volatile,以及J2SE5中新增的概念,如锁(Lock)、原子性(Atomics)、并发集合类、线程协作摘要、Executors。开发者通过这些基础的接口可以构建高并发、线程...

    Java并发编程系列- synchronized

    Java并发编程系列- synchronized;Java并发编程系列- synchronized;Java并发编程系列- synchronized;

    java并发编程

    本书全面介绍了如何使用Java 2平台进行并发编程,较上一版新增和扩展的内容包括:, ·存储模型 ·取消 ·可移植的并行编程 ·实现并发控制的工具类, Java平台提供了一套广泛而功能强大的api,工具和技术。...

    深入理解Java并发之synchronized实现原理.docx

    在 Java 中,关键字 synchronized可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块(主要是对方法或者代码块中存在共享数据的操作),同时我们还应该注意到synchronized另外一个重要的作用,...

    Java并发编程原理与实战

    理解自旋锁,死锁与重入锁.mp4 深入理解volatile原理与使用.mp4 JDK5提供的原子类的操作以及实现原理.mp4 Lock接口认识与使用.mp4 手动实现一个可重入锁.mp4 AbstractQueuedSynchronizer(AQS)详解.mp4 使用AQS重写...

    JAVA核心知识点整理(有效)

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

    Java并发volatile关键字.docx

    synchronized是阻塞式同步,在线程竞争激烈的情况下会升级为重量级锁,而volatile就可以说是JVM提供的最轻量级的同步机制。JMM告诉我们,各个线程会将共享变量从主内存中拷贝到工作内存,然后执行引擎会基于工作内存...

    Java并发编程---synchronized关键字

    Java并发编程---synchronized关键

    Java并发教程.md

    * [Synchronized和ReentrantLock的区别](#synchronized和reentrantlock的区别) * [乐观锁](#乐观锁) * [悲观锁](#悲观锁) * [独占锁](#独占锁) * [共享锁](#共享锁) * [公平锁](#公平锁) * [非公平锁](#非...

    java并发锁面试知识

    java中的乐观锁与悲观锁,synchronized与ReentrantLock重入锁的说明与比较

    Java并发编程:设计原则与模式(第二版)

    java并发方面的两大名著之一。读者将通过使用java.lang.thread类、synchronized和volatile关键字,以及wait、notify和notifyall方法,学习如何初始化、控制和协调并发操作。此外,本书还提供了有关并发编程的全方位...

    技术分享-java synchronized锁机制.pptx

    由浅入深解析synchronized锁的机制,各种锁的概念的介绍,膨胀过程,基于redis的分布式锁demo。

    深入java并发编程,使用ReentrantLock和 Synchronized加锁

    深入java并发编程,使用ReentrantLock和 Synchronized加锁

    并发synchronized详解.pdf

    synchronized

    【Java并发编程】Synchronized关键字实现原理.doc

    【Java并发编程】Synchronized关键字实现原理.doc

    Java并发编程学习笔记

    2、可重入锁与 Synchronized 的其他特性 3、ThreadLocal 的底层实现与使用 4、ReentrantLock底层实现和如何使用 5、Condition源码分析 6、ReentrantReadWriteLock底层实现原理 7、并发工具类CountDownLatch 、...

    【Java】synchronized同步锁详解

    Java锁的种类1.1 乐观锁1.2 悲观锁1.3 自旋锁1.4 其他种类锁…2. synchronized同步锁(悲观锁)2.1 synchronized 作用范围2.2 synchronized 核心组件2.3 synchronized 实现 1. Java锁的种类 1.1 乐观锁 乐观锁是一...

    Java并发机制的底层实现原理.pdf

    主要总结了:本地内存和线程安全的问题、volatile、synchronized、处理器实现并发的方式、Java实现并发的方式。

Global site tag (gtag.js) - Google Analytics