A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 冯旭君 中级黑马   /  2012-3-10 08:50  /  1610 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

package threads;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class CacheDemo {
       
        private static ReadWriteLock rwl = new ReentrantReadWriteLock();
   
        private static Map<String, Object> map = new HashMap<String, Object>();
       
       
        public static void main(String[] args) {
               
                /*for(int i = 0; i < 5; i++){
                       
                        map.put(String.valueOf(i), i);
                       
                }*/
               
                for(int i = 0; i < 10; i++){
                       
                        final int value = i;
                       
                       
                        new Thread(new Runnable(){
                                @Override
                                public void run() {
                                        // TODO Auto-generated method stub
                                        while(true){
                                                System.out.println(Thread.currentThread().getName() + " is  getting data " + getData(String.valueOf(10)));
                                        }
                                }
                        }).start();
                       
                       
                       
                }


               
               
        }
       
       

        public static Object getData(String key){
               
                Object value = null;
               
                try{
                        rwl.readLock().lock();
                        value = map.get(key);
                       
                        if(value == null){
                               
                                System.out.println(Thread.currentThread().getName() + "  hello world");
                               
                                rwl.readLock().unlock();
                                rwl.writeLock().lock();//会不会有多个线程一同加锁的情况?就是说多个线程同时运行到此句
                               
                               
                               
                                try{
                                        if(value == null){      //验证alue是否被其他线程赋值
                                               
                                                System.out.println(Thread.currentThread().getName() + "  welcome");
                                               
                                                value = "aaaa + " + key;//实际上可以从数据库中查询然后赋值
                                               
                                                map.put(key, value);
                                               
                                               
                                        }
                                       
                                }finally{
                                        rwl.readLock().lock();
                                        rwl.writeLock().unlock();
                                       
                                }
                               
                               
                               
                               
                        }
                       
                       
                       
                }catch(Exception e){
                        e.printStackTrace();
                }finally{
                        rwl.readLock().unlock();
                }
               
               
                return value;
        }

}


下面是一次运行的结果中的部分,预期是不会有两次welcom的语句出现,可是出现了三次,请帮忙调试下

Thread-2  hello world
Thread-1  hello world
Thread-0  hello world
Thread-2  welcome
Thread-2 is  getting data aaaa + 10
Thread-1  welcome
Thread-1 is  getting data aaaa + 10
Thread-1 is  getting data aaaa + 10
Thread-1 is  getting data aaaa + 10
Thread-3 is  getting data aaaa + 10
Thread-0  welcome
Thread-0 is  getting data aaaa + 10
Thread-0 is  getting data aaaa + 10
Thread-0 is  getting data aaaa + 10
Thread-0 is  getting data aaaa + 10
Thread-9 is  getting data aaaa + 10















评分

参与人数 1技术分 +2 收起 理由
职业规划-刘倩老师 + 2 赞一个!

查看全部评分

4 个回复

倒序浏览
readLock()方法允许多个线程同时读取,writeLock()会造成线程阻塞,所以:

                       rwl.readLock().lock();
                        value = map.get(key);
                        
                        if(value == null){
                                
                                System.out.println(Thread.currentThread().getName() + "  hello world");
                                
                                rwl.readLock().unlock();
                                rwl.writeLock().lock();

在这段代码中可能有多个线程同时读取数据,当一个线程加了写锁后其余线程就会阻塞,直到写锁释放,写锁释放后,刚刚阻塞的线程就会继续执行,而这时value的值仍然是null,所以仍然会执行下面这段代码
if(value == null){      //验证alue是否被其他线程赋值
                                                
          System.out.println(Thread.currentThread().getName() + "  welcome");

所以,如果你想只输出一次System.out.println(Thread.currentThread().getName() + "  welcome");
那么必须再加写锁后再获取一次value的值,只有这样才能只输出一次
回复 使用道具 举报
  
rwl.writeLock().lock();//会不会有多个线程一同加锁的情况?就是说多个线程同时运行到此句


楼上已经回答很好了,我在补充这个吧。

在cpu单核的情况下,线程并不是同步执行的,一个一个执行的,只是切换速度很快,所以实际上是一定会有先后顺序的。

在双核或多核情况下,每个核独立运行一个线程,我觉得理论上是有可能同时运行的,但实际上应该不会吧,要是会的话,核越多,多线程的安全问题越严重。
我想,多核cpu不是简单的把两个单核拼在一起吧。  这个不懂求答案!~

回复 使用道具 举报
李明伟 发表于 2012-3-10 10:36
readLock()方法允许多个线程同时读取,writeLock()会造成线程阻塞,所以:

                       rw ...

你说的很对 ,谢谢啊 ,我已经用你的方法解决了此问题啊。
回复 使用道具 举报
王睿 发表于 2012-3-10 11:13
楼上已经回答很好了,我在补充这个吧。

在cpu单核的情况下,线程并不是同步执行的,一个一个执行的, ...

俩个核心肯定不是简单的拼在一的,如果只是简单的拼在一的话,系统没有方法调度。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马