Concurrent issues: the usage of ReadWriteLock

reentrantlock 2013-12-30 10:12:19
For the following testing code,how to make the read thread can automatically be notified when the write thread finishes writing new data to the container.
In order to improve the performance of concurrent reading data, read lock and write lock are used in the programme,beacause of this,I feel difficult to implement both of threads communicate with each other.

Anybody can provide a solution to reach the objective? Please note the pre-condition: don't use another lock to replace my read-write lock,if so,concurrent performance will be reduced.That's not what I need.
Thanks a lot in advance.

------------------------------------------------------------------------------------------
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;

public class ReadWriteLockTest {

private ArrayList<String> container = new ArrayList<String>();

private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

private ReadLock readLock = readWriteLock.readLock();
private WriteLock writeLock = readWriteLock.writeLock();

public void execute(){
for(int k=0;k<1;k++){
Thread writeThread = new Thread(new Runnable(){

@Override
public void run() {

while(true){
writeLock.lock();
try{
for(int j = 0;j<3;j++){
container.add("_"+j);
}

System.out.println(Thread.currentThread().getName()+" write size:"+container.size());
}
finally{
writeLock.unlock();
}

try {
System.out.println(Thread.currentThread().getName()+" sleeping...");
TimeUnit.SECONDS.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


});

writeThread.start();
}

for(int x=0;x<2;x++){
Thread readThread = new Thread(new Runnable(){

@Override
public void run() {

while(true){
readLock.lock();
try{
TimeUnit.SECONDS.sleep(1);
while(container.size()>0){
String str = container.get(0);
synchronized(container){ // remove operation need exclusive lock when read-read
container.remove(str);
}
System.out.println(Thread.currentThread().getName()+" read data:"+str+ " size:"+ container.size());
}


} catch (Exception e){
e.printStackTrace();
}finally{
readLock.unlock();
}

try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


});

readThread.start();
}

}


/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws Exception {
ReadWriteLockTest test = new ReadWriteLockTest();
test.execute();
TimeUnit.SECONDS.sleep(100000);
}

}
...全文
371 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
reentrantlock 2014-01-08
  • 打赏
  • 举报
回复
引用 2 楼 yousteely 的回复:
将你代码的61行-67行改为 synchronized(container){ // remove operation need exclusive lock when read-read while(container.size()>0){ String str = container.get(0); container.remove(str); System.out.println(Thread.currentThread().getName()+" read data:"+str+ " size:"+ container.size()); } } 原因是readlock可以多个线程同时获取,只要writelock释放了就可以 程序运行时有可能有多个线程停在了58行的readLock.lock(); 当writelock释放后多个线程同时获得了readLock,大家也一起sleep(1),当然也同时进入了 while(container.size()>0){ String str = container.get(0); 假设container当时第0个下标的值是_0 那么就有可能有多个线程拿到了_0这个值,再依次去remove,为什么会依次去remove呢?因为你加了synchronized. 如果你要保证数据的一至性应该把synchronized放在取值之前,因为你有判断,所以就应该加在判断之前。
This is a tiny defect of my sample code,but that's not my focus. You can ignore this question,and shift your focus to my question. Restate my question again: 1. How to make the read thread can be notified when the write thread finishes writing new data to the container? 2. How to make the write thread can be notified when the read thread runs out all of the data of the container(when container becomes empty)? Note: The pre-condition is to use ReentrantReadWriteLock instead of ReentrantLock or traditional synchronized. Please use wait/notify/notifyAll mechanism or Condition.await/Condition.signal/Condition.signalAll. You can modify my sample code or write a new sample code to support your solution. Anyway,thanks a million for your comments.
steely_chen 2014-01-08
  • 打赏
  • 举报
回复
将你代码的61行-67行改为 synchronized(container){ // remove operation need exclusive lock when read-read while(container.size()>0){ String str = container.get(0); container.remove(str); System.out.println(Thread.currentThread().getName()+" read data:"+str+ " size:"+ container.size()); } } 原因是readlock可以多个线程同时获取,只要writelock释放了就可以 程序运行时有可能有多个线程停在了58行的readLock.lock(); 当writelock释放后多个线程同时获得了readLock,大家也一起sleep(1),当然也同时进入了 while(container.size()>0){ String str = container.get(0); 假设container当时第0个下标的值是_0 那么就有可能有多个线程拿到了_0这个值,再依次去remove,为什么会依次去remove呢?因为你加了synchronized. 如果你要保证数据的一至性应该把synchronized放在取值之前,因为你有判断,所以就应该加在判断之前。
reentrantlock 2014-01-08
  • 打赏
  • 举报
回复
Please note:the pre-condition is to use ReentrantReadWriteLock rather than ReentrantLock or traditional synchronized
reentrantlock 2014-01-08
  • 打赏
  • 举报
回复
引用 6 楼 zxcvbnm11920 的回复:

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

public class ReadWriteLockTest {
    private ArrayList<String> container = new ArrayList<String>();
    private int maxNum = 10;

    public void execute(){
        for(int k=0;k<1;k++){
            Thread writeThread = new Thread(new Runnable(){
                @Override
                public void run() {
                    while(true){
                        try{
                            while(container.size()<maxNum){
                                synchronized(container){
                                    for(int j = 0;j<3;j++){
                                        if (container.size()<maxNum) {
                                            container.add("_"+j);
                                            TimeUnit.SECONDS.sleep(1);
                                            System.out.println(Thread.currentThread().getName()+" write size:"+container.size());
                                        }
                                    }
                                    container.notifyAll();
                                    System.out.println("notify read thread");
                                    if (container.size()==maxNum) {
                                        System.out.println(Thread.currentThread().getName()+" sleeping...");
                                        container.wait();
                                    }
                                }
                                TimeUnit.SECONDS.sleep(1);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            writeThread.start();
        }

        for(int x=0;x<2;x++){
            Thread readThread = new Thread(new Runnable(){
                @Override
                public void run() {
                    while(true){
                        try{
                            while(container.size()>0){
                                synchronized(container){
                                    int index = container.size();
                                    if (index>0) {
                                        String str = container.get(0);
                                        container.remove(0);
                                        TimeUnit.SECONDS.sleep(1);
                                        System.out.println(Thread.currentThread().getName()+" read data:"+str+ "  size:"+ container.size());
                                        if (index==1) {
                                            container.notifyAll();
                                            System.out.println("notify write thread");
                                        }
                                    } else {
                                        container.wait();
                                    }
                                }
                            }
                        } catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }
            });
            readThread.start();
        }

    }


    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws Exception {
        ReadWriteLockTest test = new ReadWriteLockTest();
        test.execute();
        TimeUnit.SECONDS.sleep(100000);
    }
}
改别人代码好痛苦。 多线程 生产者消费者 http://blog.csdn.net/shijinupc/article/details/7250407
Restate my question again: 1. How to make the read thread can be notified when the write thread finishes writing new data to the container? 2. How to make the write thread can be notified when the read thread runs out all of the data of the container(when container becomes empty)? Note: The pre-condition is to use ReentrantReadWriteLock instead of ReentrantLock or traditional synchronized. Please use wait/notify/notifyAll mechanism or Condition.await/Condition.signal/Condition.signalAll. You can modify my sample code or write a new sample code to support your solution. Anyway,thanks a million for your comments. Besides,I'm familiar with producer consumer pattern,but that's not my question.
骑士的崛起 2014-01-08
  • 打赏
  • 举报
回复

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

public class ReadWriteLockTest {
    private ArrayList<String> container = new ArrayList<String>();
    private int maxNum = 10;

    public void execute(){
        for(int k=0;k<1;k++){
            Thread writeThread = new Thread(new Runnable(){
                @Override
                public void run() {
                    while(true){
                        try{
                            while(container.size()<maxNum){
                                synchronized(container){
                                    for(int j = 0;j<3;j++){
                                        if (container.size()<maxNum) {
                                            container.add("_"+j);
                                            TimeUnit.SECONDS.sleep(1);
                                            System.out.println(Thread.currentThread().getName()+" write size:"+container.size());
                                        }
                                    }
                                    container.notifyAll();
                                    System.out.println("notify read thread");
                                    if (container.size()==maxNum) {
                                        System.out.println(Thread.currentThread().getName()+" sleeping...");
                                        container.wait();
                                    }
                                }
                                TimeUnit.SECONDS.sleep(1);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            writeThread.start();
        }

        for(int x=0;x<2;x++){
            Thread readThread = new Thread(new Runnable(){
                @Override
                public void run() {
                    while(true){
                        try{
                            while(container.size()>0){
                                synchronized(container){
                                    int index = container.size();
                                    if (index>0) {
                                        String str = container.get(0);
                                        container.remove(0);
                                        TimeUnit.SECONDS.sleep(1);
                                        System.out.println(Thread.currentThread().getName()+" read data:"+str+ "  size:"+ container.size());
                                        if (index==1) {
                                            container.notifyAll();
                                            System.out.println("notify write thread");
                                        }
                                    } else {
                                        container.wait();
                                    }
                                }
                            }
                        } catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }
            });
            readThread.start();
        }

    }


    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws Exception {
        ReadWriteLockTest test = new ReadWriteLockTest();
        test.execute();
        TimeUnit.SECONDS.sleep(100000);
    }
}
改别人代码好痛苦。 多线程 生产者消费者 http://blog.csdn.net/shijinupc/article/details/7250407
reentrantlock 2014-01-08
  • 打赏
  • 举报
回复
引用 4 楼 yousteely 的回复:
可能对你的E文理解有限,并不是你E文写得有问题,是我的E文比较有限。 问题1: 怎么才能让读的线程在写线程完成了数据写入后才开始工作 问题2: 怎么才能让写的线程是在读线程移除了所有的数据后才开始工作 答1: 你的代码再加上我之后提供的修改已经可以做到了 答2: 不要使用读写锁,即然要读写同步就使用互斥。也可以使用标志位。 针对问题2的伪代码 class someClass{ volatile boolean isReading = False; wirteBlock{ if (!isReading){ write date } } readBlock{ isReading = true; read date isReading = false; } } 如果不对而且还没有大牛出现来解释一下,请楼主用中文解释你的问题。 我只读到了初三就被学校以无心学习开除了,初一才开始学abc,英文水平实在有限。
Thanks for your comments.However,I feel you cannot help me fix this issue.
steely_chen 2014-01-08
  • 打赏
  • 举报
回复
可能对你的E文理解有限,并不是你E文写得有问题,是我的E文比较有限。 问题1: 怎么才能让读的线程在写线程完成了数据写入后才开始工作 问题2: 怎么才能让写的线程是在读线程移除了所有的数据后才开始工作 答1: 你的代码再加上我之后提供的修改已经可以做到了 答2: 不要使用读写锁,即然要读写同步就使用互斥。也可以使用标志位。 针对问题2的伪代码 class someClass{ volatile boolean isReading = False; wirteBlock{ if (!isReading){ write date } } readBlock{ isReading = true; read date isReading = false; } } 如果不对而且还没有大牛出现来解释一下,请楼主用中文解释你的问题。 我只读到了初三就被学校以无心学习开除了,初一才开始学abc,英文水平实在有限。
梦亦无痕 2014-01-06
  • 打赏
  • 举报
回复
你是为嘛一定要用英语?

25,985

社区成员

发帖
与我相关
我的任务
社区描述
高性能WEB开发
社区管理员
  • 高性能WEB开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧