首页 > 图灵资讯 > java面试题>正文

如何在Java中实现可重入读写锁(ReentrantReadWriteLock)?

2025-02-17 14:21:55

在Java中,如果我们想让多个线程可以同时读取数据,但写数据的时候又要确保只有一个线程能操作,并且写的时候不能有线程在读,那就可以用一种叫“读写锁”的机制。而“可重入读写锁”(ReentrantReadWriteLock)正是Java里提供的一个现成的工具类,专门用来解决这种问题。


什么是可重入读写锁?

  1. 读锁和写锁分开

    • 读锁:允许多个线程同时读取数据,但不能写。
    • 写锁:只有一个线程能写,同时禁止其他线程读或写。
  2. 可重入:意思是,如果一个线程已经拿到了锁,它可以再次进入锁的代码块,而不会被锁挡住。比如,一个线程已经获取了写锁,接下来如果它又想获取写锁,就不会再卡住。


为什么要用可重入读写锁?

举个例子:想象一下,你和朋友们去图书馆借书。

  • 如果你们只是“看书”(读操作),大家可以一起看,不会互相打扰。
  • 但如果你需要“修改书本内容”(写操作),为了不影响别人看书,图书馆会让所有人先停下来,等你修改完后再继续看。

在程序里也是类似的:

  • 读操作是“多线程共享”,效率更高。
  • 写操作是“单线程独占”,保证数据的安全性。

如何在Java中实现?

Java提供了ReentrantReadWriteLock这个工具类,它分为两部分:

  • 读锁(read lock):用来控制读操作。
  • 写锁(write lock):用来控制写操作。

使用它的步骤:

  1. 首先,创建一个ReentrantReadWriteLock对象。
  2. 通过这个对象,可以分别获取“读锁”和“写锁”。
  3. 在需要读或者写的地方,先获取对应的锁。
  4. 用完后,记得释放锁。

锁的具体行为:

  • 如果一个线程获取了读锁,其他线程也可以获取读锁,但不能获取写锁。
  • 如果一个线程获取了写锁,其他线程既不能获取读锁,也不能获取写锁。
  • 如果有线程正在等着获取写锁,新的读锁请求会被阻塞,优先让写锁完成。

注意事项

  1. 避免死锁:一定要按顺序释放锁。如果一个线程同时持有读锁和写锁,释放时需要确保写锁先释放,然后再释放读锁。
  2. 性能选择:读写锁适合“读多写少”的场景。如果写操作很频繁,可能会降低性能。
  3. 公平性ReentrantReadWriteLock默认是非公平的,也就是说,线程获取锁的顺序不一定按先来先得。如果需要公平性,可以通过构造方法设置。

总结

ReentrantReadWriteLock就像图书馆管理员一样,负责管理“读者”和“修改者”的进出:

  • 读者可以一起进来,但修改者需要单独操作。
  • 如果有人正在修改,读者和其他修改者都得等。
  • 如果用的人多了,还可以调整规则,让大家按顺序来。
上一篇 解释Java中的CopyOnWriteArrayList,它的优缺点是什么?
下一篇 返回列表

文章素材均来源于网络,如有侵权,请联系管理员删除。