线程-读写锁。

举报
yd_57386892 发表于 2021/05/04 01:14:36 2021/05/04
【摘要】 读写锁。我们上次温习了synchronized与Lock.我们遗留了一个问题,就是想让读读不互斥,因为多线程同时读取数据并不会破坏数据。如果能实现读读不用互斥,那将大大提升了多线程读性能。于是我们引入了读写锁ReentrantReadWriteLock。ReentrantReadWriteLock可以专门创建一个读锁和写锁。读锁:读读不互斥,但是读写互斥。 写锁:不但读写互斥...

读写锁。我们上次温习了synchronized与Lock.我们遗留了一个问题,就是想让读读不互斥,因为多线程同时读取数据并不会破坏数据。如果能实现读读不用互斥,那将大大提升了多线程读性能。于是我们引入了读写锁ReentrantReadWriteLock。ReentrantReadWriteLock可以专门创建一个读锁和写锁。读锁:读读不互斥,但是读写互斥。 写锁:不但读写互斥,而且写写也互斥。

创建一个读写锁

  ReadWriteLock rwl = new ReentrantReadWriteLock();

  读锁:  rwl.readLock().lock() 与 rwl.readLock().unlock(); 成对出现; 读完了公共变量,其它线程才能写这个公共变量(赋值),但是多个线程可以同时读。

  写锁: rwl.writeLock().lock() 与  rwl.writeLock().unlock(); 成对出现;写完了公共变量,其它线程才能写或读这个公共变量。

 以下示例代码展示了读锁与写锁。创建两个一个Queue自定义类,有一个get()和put()方法,在get()方法里使用读锁,在put()里使用写锁,它们都操作一个公共数据Object data。


  
  1. package testFuture;
  2. import java.util.Random;
  3. import java.util.concurrent.locks.ReadWriteLock;
  4. import java.util.concurrent.locks.ReentrantReadWriteLock;
  5. public class LockTest {
  6. public static void main(String[] args) {
  7. final Queue3 q3 = new Queue3();
  8. for(int i=0;i<3;i++)
  9. {
  10. new Thread(){
  11. public void run(){
  12. while(true){
  13. q3.get();
  14. }
  15. }
  16. }.start();
  17. new Thread(){
  18. public void run(){
  19. while(true){
  20. q3.put(new Random().nextInt(10000));
  21. }
  22. }
  23. }.start();
  24. }
  25. }
  26. }
  27. synchronized
  28. class Queue3{
  29. private Object data = null;//共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。
  30. ReadWriteLock rwl = new ReentrantReadWriteLock();
  31. public void get(){
  32. rwl.readLock().lock();
  33. try {
  34. System.out.println(Thread.currentThread().getName() + " be ready to read data!");
  35. Thread.sleep((long)(Math.random()*1000));
  36. System.out.println(Thread.currentThread().getName() + "have read data :" + data);
  37. } catch (InterruptedException e) {
  38. e.printStackTrace();
  39. }finally{
  40. rwl.readLock().unlock();
  41. }
  42. }
  43. public void put(Object data){
  44. rwl.writeLock().lock();
  45. try {
  46. System.out.println(Thread.currentThread().getName() + " be ready to write data!");
  47. Thread.sleep((long)(Math.random()*1000));
  48. this.data = data;
  49. System.out.println(Thread.currentThread().getName() + " have write data: " + data);
  50. } catch (InterruptedException e) {
  51. e.printStackTrace();
  52. }finally{
  53. rwl.writeLock().unlock();
  54. }
  55. }
  56. }

打印日志如下:

Thread-2 be ready to read data!
Thread-0 be ready to read data!
Thread-4 be ready to read data!
Thread-0have read data :null
Thread-2have read data :null
Thread-4have read data :null
Thread-5 be ready to write data!
Thread-5 have write data: 8687
Thread-5 be ready to write data!
Thread-5 have write data: 8653
Thread-1 be ready to write data!
Thread-1 have write data: 7614
Thread-1 be ready to write data!
Thread-1 have write data: 4680
Thread-3 be ready to write data!
Thread-3 have write data: 473
Thread-0 be ready to read data!
Thread-2 be ready to read data!
Thread-4 be ready to read data!
Thread-0have read data :473
Thread-4have read data :473
Thread-2have read data :473
Thread-5 be ready to write data!
Thread-5 have write data: 7706
Thread-1 be ready to write data!
Thread-1 have write data: 7828
Thread-1 be ready to write data!
Thread-1 have write data: 6492
Thread-3 be ready to write data!
Thread-3 have write data: 6439
Thread-3 be ready to write data!
Thread-3 have write data: 4558
Thread-0 be ready to read data!
Thread-4 be ready to read data!
Thread-2 be ready to read data!
Thread-0have read data :4558
Thread-4have read data :4558
Thread-2have read data :4558

 

我们会发现总共有6个线程:0,2,4线程是读,1,3,5线程是写数据,当5在写数据的时候,put方法输出以下2条日志:

Thread-5 be ready to write data!
Thread-5 have write data: 8687

这2条日志之间,并没有其它线程打扰。5写完了,接着才是线程1写数据,输出日志:

Thread-1 be ready to write data!
Thread-1 have write data: 7614

同样,这2条日志之间,没有其它线程打扰。

假设线程5在执行put写数据的时候,输出日志如下,则是被线程1打扰了:

Thread-5 be ready to write data!

Thread-1 be ready to write data!
Thread-5 have write data: 8687

Thread-1 have write data: 7614

线程5的本意是让data变为8676,结果当线程5的put返回的时候,实际上data已被线程1修改成了7614,线程5还摸不着头脑,自己怎么就做错了,很简单的事情都能出错。

 

 

 

文章来源: blog.csdn.net,作者:冉航--小虾米,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/gaoxiaoweiandy/article/details/116099251

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。