package com.yonge.lock;
import java.util.Random;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 需求:多线程操作同一数据,可以多线程同时读数据,只能一个线程修改数据;
* @author wb-gaoy
* @version $Id: ShareData.java,v 0.1 2011-12-31 下午3:00:09 wb-gaoy Exp $
*/
public class ShareData {
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private String data;
public ShareData(String data) {
this.data = data;
}
/**
* 修改数据的方法
* @param str
*/
public void merge(String str) {
lock.writeLock().lock();
System.out.println("ThreadName:" + Thread.currentThread().getName() + "-"
+ Thread.currentThread().getId() + " locking...");
try {
data = str;
System.out.println("ThreadName:" + Thread.currentThread().getName() + "-"
+ Thread.currentThread().getId() + " 修改为:" + str);
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("ThreadName:" + Thread.currentThread().getName() + "-"
+ Thread.currentThread().getId() + " unlock...");
lock.writeLock().unlock();
}
}
/**
* 获取数据的方法
*/
public String get() {
lock.readLock().lock();
System.out.println("ThreadName:" + Thread.currentThread().getName() + "-"
+ Thread.currentThread().getId() + " locking...");
try {
System.out.println("ThreadName:" + Thread.currentThread().getName() + "-"
+ Thread.currentThread().getId() + " 获取为:" + data);
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.readLock().unlock();
System.out.println("ThreadName:" + Thread.currentThread().getName() + "-"
+ Thread.currentThread().getId() + " unlock...");
}
return data;
}
/**
* @param args
*/
public static void main(String[] args) {
final ShareData shareData = new ShareData("Hello,World!!");
for (int i = 0; i < 50; i++) {
new Thread(new Runnable() {
@Override
public void run() {
shareData.get();
}
}, "A").start();
new Thread(new Runnable() {
@Override
public void run() {
shareData.merge(new Random().nextLong() + "");
}
}, "B").start();
}
}
/**
* 总结:
* 1、readLock在没有被释放的时候可以被多个线程同时读取,此时还可以重入writeLock锁
* 2、writeLock在没有被释放的时候其他锁不能进入,也不能重入readLock锁,直到writeLock被解锁
*/
}
分享到:
相关推荐
ReentrantReadWriteLock使用`state`字段来存储读写锁的状态,高16位表示读锁的同步状态,低16位表示写锁的同步状态。通过位运算来判断和更新读写锁的状态: - `SHARED_SHIFT`:读锁状态的位移量。 - `SHARED_UNIT`...
读写锁通过`ReentrantReadWriteLock`类的实例来创建,该类提供了`readLock()`和`writeLock()`方法,分别用于获取读锁和写锁。 ```java ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); Lock readLock...
2. **ReentrantReadWriteLock的底层实现原理** - ReentrantReadWriteLock基于AbstractQueuedSynchronizer(AQS)实现。AQS是一个用于构建锁和同步组件的基础框架,它使用一个FIFO的等待队列来管理线程的阻塞和唤醒...
在上面的代码中,我们使用了RedisTemplate来操作Redis缓存,并使用ReentrantReadWriteLock来实现读写锁,以确保缓存的线程安全。 最后,我们需要在Mapper接口中使用自定义的缓存管理类: ```java @Mapper public ...
2. **ReentrantReadWriteLock**: - `ReentrantReadWriteLock`是Java提供的可重入的读写锁实现,它继承自`AbstractQueuedSynchronizer`(AQS)。可重入意味着一个线程可以多次获取同一锁,这在递归调用或者锁嵌套时...
- 在`readwritelock`这个示例中,可能包含了创建`ReentrantReadWriteLock`对象,获取读锁和写锁的代码,并通过注释解释了其工作原理和使用方法。 4. **读写锁的实现原理**: - 读写锁通常使用两个内部锁来实现:...
2. 文件操作:File类的常用方法,FileInputStream和FileOutputStream的使用。 3. 缓冲流:BufferedReader、BufferedWriter等缓冲流的使用。 4. NIO(New IO):通道(Channel)、缓冲区(Buffer)、选择器(Selector...
生产者线程使用put()方法添加元素,消费者线程使用take()方法取出元素。`BlockingQueue`内部实现了线程安全的队列操作,避免了竞态条件。 6) **死锁的产生与解决**:死锁发生在两个或更多线程互相等待对方释放资源...
16.4.9 防止错误的使用wait、notify、notifyAll方法 371 16.5 获取当前正在运行的线程 372 16.6 volatile关键字的含义与使用 372 16.7 小结 373 第17章 高级线程开发 374 17.1 线程池的使用 374 17.1.1...
- **线程通信**:`wait()`, `notify()`, `notifyAll()`是用于线程间通信的方法,但必须在`synchronized`块或方法中使用。 2. **并发工具类** - **ExecutorService**:Java并发框架中的核心组件,用于管理线程池,...
在 UseReentrantLock 类中,我们定义了一个私有的 ReentrantLock 对象 lock,并在 method1 和 method2 方法中使用 lock.lock() 和 lock.unlock() 方法来获取和释放锁。在 main 方法中,我们创建了一个线程 t1,并在 ...
- 使用方法:在Unix/Linux系统中,可以使用命令`kill -3 <pid>`来生成`Thread Dump`;在Windows系统中,则可以通过按下`Ctrl + Break`键来生成。 - 分析方法:查看线程的状态,比如`WAITING`、`BLOCKED`等状态可以...
3. Lock接口:了解ReentrantLock、ReentrantReadWriteLock等高级锁的使用。 六、IO流 1. 文件操作:理解File类的基本操作,如创建、删除、重命名文件。 2. 字节流与字符流:掌握InputStream、OutputStream、Reader...
3. Lock接口:了解ReentrantLock、ReentrantReadWriteLock的使用,与synchronized的区别。 五、IO与NIO 1. 流:掌握InputStream、OutputStream、Reader、Writer及其子类的使用。 2. NIO:理解非阻塞I/O的特点,...
在Java中,我们可以使用`java.util.concurrent.locks`包下的`ReentrantReadWriteLock`类来实现。这个锁提供了一种方式,使得多个线程可以同时读取数据,但只允许一个线程写入数据,从而保证了数据的一致性。 `...
#### 2. Java并发包源码分析 让我们先来看一个Java并发包中的示例代码片段: ```java private int dowait(boolean timed, long nanos) throws InterruptedException, BrokenBarrierException, TimeoutException ...
对于实现高效缓存的问题,可以使用`ReentrantReadWriteLock`来区分读写锁,这样可以允许多个读者同时访问,但只允许一个写者修改缓存,从而提高并发性能。 #### 3. wait 和 sleep 方法的区别 - **区别**: - `...
- 使用`ReentrantReadWriteLock`并正确使用`readLock()`和`writeLock()`方法。 - 避免死锁和活锁的情况,确保线程间的锁获取顺序一致。 - 检查所有锁的释放,避免内存泄漏或线程阻塞。 - 检查共享数据结构是否为线程...
### 二、使用Java语言编写读者-写者问题 **读者-写者问题**是一种经典的多线程同步问题,主要涉及多个读者线程和一个写者线程共享一个资源的情况。当有读者正在读取资源时,允许其他读者同时读取;但如果有写者想要...
- **实现高效缓存**:可以使用ReentrantReadWriteLock来实现读写锁。读取操作可以并发进行,而写操作则需独占锁,以确保数据的一致性。 #### 3. `wait`与`sleep`的区别 - **问题描述**:`wait`和`sleep`方法有何...