简单的并发控制可以通过synchronized关键字来完成。
synchronized通过锁定对象,从而实现并发的控制。
但是遇到一下一种情况,就会出现意想之外的结果。
一般来说,我们要实现写入和写入互斥,读取和写入互斥,读取和读取互斥,
在set和get方法加入sychronized修饰符:
public synchronized void set(int data) {...} public synchronized void get() {...}
但是我们发现,虽然写入和写入互斥了,读取和写入也互斥了,但是读取和读取之间也互斥了,
不能并发执行,效率较低,用读写锁实现代码如下:
import java.util.Random; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class ReadWriteLockTest { private int data;// 共享数据 private ReadWriteLock rwl = new ReentrantReadWriteLock(); public void set(int data) { rwl.writeLock().lock();// 取到写锁 rwl.readLock().lock(); try { System.out.println(Thread.currentThread().getName() + "准备写入数据"); try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } this.data = data; System.out.println(Thread.currentThread().getName() + "写入" + this.data); } finally { rwl.writeLock().unlock();// 释放写锁 rwl.readLock().unlock(); } } public void get() { rwl.readLock().lock();// 取到读锁 try { System.out.println(Thread.currentThread().getName() + "准备读取数据"); try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "读取" + this.data); } finally { rwl.readLock().unlock();// 释放读锁 } } public static void main(String args[]){ final ReadWriteLockTest test = new ReadWriteLockTest(); new Thread() { public void run() { test.set(new Random().nextInt(15)); test.get(); }; }.start(); new Thread() { public void run() { test.set(new Random().nextInt(25)); test.get(); }; }.start(); new Thread() { public void run() { test.set(new Random().nextInt(35)); test.get(); }; }.start(); } }
对于Java concurrent包里的并发,有这么一段话:
什么时候选择用 ReentrantLock 代替 synchronized
既然如此,我们什么时候才应该使用 ReentrantLock 呢?
答案非常简单 —— 在确实需要一些 synchronized 所没有的特性的时候,
比如时间锁等候、可中断锁等候、无块结构锁、多个条件变量或者锁投票。
ReentrantLock 还具有可伸缩性的好处,应当在高度争用的情况下使用它,
但是请记住,大多数 synchronized 块几乎从来没有出现过争用,
所以可以把高度争用放在一边。我建议用 synchronized 开发,
直到确实证明 synchronized 不合适,而不要仅仅是假设如果使用 ReentrantLock “性能会更好”。
请记住,这些是供高级用户使用的高级工具。
一如既往,首先要把事情做好,然后再考虑是不是有必要做得更快。
ref:
相关推荐
Java多线程读大文件 java多线程写文件:多线程往队列中写入数据
主要介绍了Java多线程编程之读写锁ReadWriteLock用法实例,本文直接给出编码实例,需要的朋友可以参考下
多线程对文件读写操作(java),提高对文件读写效率。
主要介绍了举例说明Java多线程编程中读写锁的使用,文中的例子很好地说明了Java的自带读写锁ReentrantReadWriteLock的使用,需要的朋友可以参考下
《秒杀多线程第十六篇 多线程十大经典案例之一 双线程读写队列数据》 http://blog.csdn.net/morewindows/article/details/8646902 配套程序 在《秒杀多线程系列》的前十五篇中介绍多线程的相关概念,多线程同步互斥...
Java多线程两个例子,一个是自定义线程池方法实现多线程运行个数的控制,可以解决多线程内存不足的问题。另一个是利用线程通信,读写先关的典型实例
java多线程设计immutable实例源码,多线程读写防止非安全问题
主要介绍了Java多线程之readwritelock读写分离的相关内容,文中涉及具体实例代码,具有一定参考价值,需要的朋友可以了解下。
主要介绍了Java多线程编程中线程锁与读写锁的使用示例,锁是控制程序多线程并发的重要手段,需要的朋友可以参考下
本文实例讲述了C#解决SQlite并发异常问题的方法。分享给大家供大家参考,...作者利用读写锁(ReaderWriterLock),达到了多线程安全访问的目标。 using System; using System.Collections.Generic; using System.Text;
本文主要介绍java多线程的知识,这里整理了相关资料及简单示例代码,有兴趣的小伙伴可以参考下
1.讲解了Java多线程的基础, 包括Thread类的核心API的使用。2.讲解了在多线程中对并发访问的控制, 主要就是synchronized的使用, 由于此关键字在使用上非常灵活, 所以书中用了很多案例来介绍此关键字的使用, 为...
//释放所获取的锁2) 然后还需要定义一个读写锁的接口,这个接口的作用就是定义读写锁的特性//获取当前有多少线程正在执行写操作int getWritingWri
在主线程中通过控制台读取键盘...服务器在收到一个socket连接之后,把该socket保存到队列中,并对队列中的每个socket开启各自的读写线程。测试可以在不同控制台运行server和client,服务器接收消息时,会显示消息来源
在char01包里放置Java多线程基本知识的代码。内容如下: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 在char02包里放置了Java对变量和对象并发访问的知识的代码...
主要介绍了java多线程读写文件示例,需要的朋友可以参考下
如果多线程同时读写(这里的指不同的线程用使用的是不同的Helper实例),后面的就会遇到android.database.sqlite.SQLiteException: database is locked这样的异常。对于这样的问题,解决的办法就是keep single ...
线程安全问题的产生是因为多个线程并发访问共享数据造成的,如果能将多个线程对共享数据的并发访问改为串行访问,即一个共享数据同一时刻只能被一个线程访问,就可以避免线程安全问题。锁正是基于这种思路实现的一种...
java程序(利用线程)。一个线程往成绩单中写入课程名和成绩,一个线程从成绩单中读出课程和成绩,并将课程和成绩显示在屏幕上。