我们启动了5个读线程和2个写线程,运行结果如下:
Thread-0 waiting for read...
Thread-1 waiting for read...
Thread-2 waiting for read...
Thread-3 waiting for read...
Thread-4 waiting for read...
Thread-5 waiting for write...
Thread-6 waiting for write...
Thread-4 reads data: AAAAAAAAAA
Thread-3 reads data: AAAAAAAAAA
Thread-2 reads data: AAAAAAAAAA
Thread-1 reads data: AAAAAAAAAA
Thread-0 reads data: AAAAAAAAAA
Thread-5 wrote data: EEEEEEEEEE
Thread-6 wrote data: MMMMMMMMMM
Thread-1 waiting for read...
Thread-4 waiting for read...
Thread-1 reads data: MMMMMMMMMM
Thread-4 reads data: MMMMMMMMMM
Thread-2 waiting for read...
Thread-2 reads data: MMMMMMMMMM
Thread-0 waiting for read...
Thread-0 reads data: MMMMMMMMMM
Thread-4 waiting for read...
Thread-4 reads data: MMMMMMMMMM
Thread-2 waiting for read...
Thread-5 waiting for write...
Thread-2 reads data: MMMMMMMMMM
Thread-5 wrote data: GGGGGGGGGG
Thread-6 waiting for write...
Thread-6 wrote data: AAAAAAAAAA
Thread-3 waiting for read...
Thread-3 reads data: AAAAAAAAAA
......
可以看到,每次读/写都是完整的原子操作,因为我们每次写入的都是10个相同字符。并且,每次读出的都是最近一次写入的内容。
如果去掉ReadWriteLock:
package com.crackj2ee.thread;
public class DataHandler {
// store data:
private char[] buffer = "AAAAAAAAAA".toCharArray();
public char[] read(String name) throws InterruptedException {
char[] data = doRead();
System.out.println(name + " reads data: " + new String(data));
return data;
}
public void write(String name, char[] data) throws InterruptedException {
System.out.println(name + " wrote data: " + new String(data));
doWrite(data);
}
private char[] doRead() {
char[] ret = new char[10];
for(int i=0; i<10; i++) {
ret[i] = buffer[i];
sleep(3);
}
return ret;
}
private void doWrite(char[] data) {
for(int i=0; i<10; i++) {
buffer[i] = data[i];
sleep(10);
}
}
private void sleep(int ms) {
try {
Thread.sleep(ms);
}
catch(InterruptedException ie) {}
}
}
运行结果如下:
Thread-5 wrote data: AAAAAAAAAA
Thread-6 wrote data: MMMMMMMMMM
Thread-0 reads data: AAAAAAAAAA
Thread-1 reads data: AAAAAAAAAA
Thread-2 reads data: AAAAAAAAAA
Thread-3 reads data: AAAAAAAAAA
Thread-4 reads data: AAAAAAAAAA
Thread-2 reads data: MAAAAAAAAA
Thread-3 reads data: MAAAAAAAAA
Thread-5 wrote data: CCCCCCCCCC
Thread-1 reads data: MAAAAAAAAA
Thread-0 reads data: MAAAAAAAAA
Thread-4 reads data: MAAAAAAAAA
Thread-6 wrote data: EEEEEEEEEE
Thread-3 reads data: EEEEECCCCC
Thread-4 reads data: EEEEEEEEEC
Thread-1 reads data: EEEEEEEEEE
可以看到在Thread-6写入EEEEEEEEEE的过程中,3个线程读取的内容是不同的。
分享到:
相关推荐
`main()`方法创建了三个线程,一个用于写操作,两个用于读操作。当写线程运行时,其他读线程会被阻塞,直到写线程完成写操作并释放写锁。 总的来说,ReadWriteLock提供了一种高效且灵活的方式来管理对共享资源的...
PricesInfo 类有三个方法:getPrice1()、getPrice2()和setPrices()。getPrice1()和getPrice2()方法使用读锁来锁定资源,而setPrices()方法使用写锁来锁定资源。 在多线程环境下,我们可以使用多个线程来读取 ...
高并发编程第三阶段27讲 ReadWriteLock&ReentrantReadWriteLock详细讲解_.mp4 高并发编程第三阶段28讲 Condition初步使用,提出几个疑问_.mp4 高并发编程第三阶段29讲 关于Condition疑问的几个小实验,...
高并发编程第三阶段27讲 ReadWriteLock&ReentrantReadWriteLock详细讲解_.mp4 高并发编程第三阶段28讲 Condition初步使用,提出几个疑问_.mp4 高并发编程第三阶段29讲 关于Condition疑问的几个小实验,...
第三章:锁机制 3.1 ReentrantLock 3.2 ReadWriteLock 3.3 StampedLock 第四章:同步辅助工具 4.1 CountDownLatch 4.2 CyclicBarrier 4.3 Semaphore 4.4 Exchanger 第五章:原子类和无锁编程 5.1 ...
- `ReadWriteLockImpl`类:实现了`ReadWriteLock`接口,内部维护了三个计数器,分别记录正在写入的线程数、等待写入的线程数和正在读取的线程数。此外,还包含一个对象锁`MUTEX`,用于同步对这些计数器的访问。 - ...
三、Condition接口的设计与实现 Condition接口提供了比synchronized更细粒度的线程间通信机制,它允许线程等待特定条件,而不仅仅是等待锁的释放。当线程调用condition的await()方法时,会释放当前持有的锁,进入...
### 三、StampLock详解 #### 3.1 StampLock简介 `StampLock`是Java 8引入的一种新的同步机制,它提供了比`ReentrantReadWriteLock`更细粒度的控制。与传统的读写锁不同,`StampLock`提供了一个版本号(或称作“戳记...
8. Lock接口 (ReentrantLock 可重入锁) 特性 ReentantLock 继承接口 Lock 并实现了接口中定义的方法, 它是一种可重入锁, 除了能完成 synchronized 所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁...
⼀、ReentrantLock重⼊锁 1.1> 概述 1.2> 中断响应 lockInterruptibly() ...三、Semaphore信号量 四、ReadWriteLock读写锁 五、CountDownLatch倒计时器 六、CyclicBarrier循环栅栏 七、LockSupport线程阻塞⼯具类
为了验证Lock2Lock重构工具的有效性,使用了三个测试案例:红黑树、消费者生产者问题模型和SPECjbb2005。这些测试案例涵盖了不同的并发场景和数据结构,能够从不同的维度测试重构工具的性能。 7. 文档信息 文档中...
Java 中的 ReentrantReadWriteLock 类是 ReadWriteLock 接口的实现类。 CAS CAS 是 Compare And Swap,即比较和交换。CAS 使用一个期望值与一个变量的当前值比较,如果当前变量的值与期望值相等,则用一个新值来...
例如,有T1、T2、T3三个线程,我们希望T2在T1执行完毕后再执行,T3则需在T2执行完毕后执行。可以通过`Thread.join()`方法来实现这一需求。 **方法介绍:** `join()`方法的功能是使异步执行的线程变为同步执行。即在...
三、其他并发工具 - **Semaphore(信号量)**:控制同时访问特定资源的线程数量。 - **CountDownLatch**:一次性计数器,用于等待多个线程完成操作。 - **CyclicBarrier**:允许一组线程等待彼此到达某个屏障点后...
#### 三、Semaphore 信号量 - **概述**:`Semaphore` 是一种用于控制同时访问特定资源的线程数量的同步工具类。 - **常用方法**: - `acquire()`:获取许可,如果没有足够的许可,则等待。 - `release()`:释放一...
#### 三、注意事项 1. **锁的获取与释放:** - 调用 `wait()`, `notify()`, `notifyAll()` 必须在 `synchronized` 块中,即必须先获得锁。 - 当线程调用 `wait()` 时,会释放锁;当线程被唤醒并重新获得锁后,会从...
#### 三、独享锁与共享锁 **1. 独享锁** 独享锁也称为排他锁,指的是在某个时间段内只允许一个线程获取锁,这意味着如果当前线程获得了锁,则其他线程必须等待直到该线程释放锁。 **2. 共享锁** 共享锁允许多个...
2. 锁机制:理解synchronized和Lock的区别,掌握ReentrantLock、ReadWriteLock的用法。 3. CountDownLatch、CyclicBarrier、Semaphore等并发工具类的应用场景及实现方式。 三、Java虚拟机(JVM) 1. 类加载机制:...
Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-...12. 第三方框架整合:Redisson可以与多种第三方框架进行整合,如Spring框架、Spring Cache、Hibernate、Java缓存标准规范JCache API(JSR-107)等。