`
dacoolbaby
  • 浏览: 1254354 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Java多线程包之读写锁

    博客分类:
  • Java
阅读更多

简单的并发控制可以通过synchronized关键字来完成。

synchronized通过锁定对象,从而实现并发的控制。

 

但是遇到一下一种情况,就会出现意想之外的结果。

 

一般来说,我们要实现写入和写入互斥,读取和写入互斥,读取和读取互斥,

在set和get方法加入sychronized修饰符:

 

public synchronized void set(int data) {...}      
public synchronized void get() {...} 

 

但是我们发现,虽然写入和写入互斥了,读取和写入也互斥了,但是读取和读取之间也互斥了,

不能并发执行,效率较低,用读写锁实现代码如下:

 

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockTest {
    private int data;// 共享数据

    private ReadWriteLock rwl = new ReentrantReadWriteLock();

    public void set(int data) {
        
        rwl.writeLock().lock();// 取到写锁
        rwl.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "准备写入数据");
            try {
                Thread.sleep(20);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.data = data;
            System.out.println(Thread.currentThread().getName() + "写入" + this.data);
        } finally {
            rwl.writeLock().unlock();// 释放写锁
            rwl.readLock().unlock();
        }
    }

    public void get() {
        rwl.readLock().lock();// 取到读锁
        try {
            System.out.println(Thread.currentThread().getName() + "准备读取数据");
            try {
                Thread.sleep(20);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "读取" + this.data);
        } finally {
            rwl.readLock().unlock();// 释放读锁
        }
    }
    
    
    public static void main(String args[]){
        
        final ReadWriteLockTest test = new ReadWriteLockTest();
        
        new Thread() {
            public void run() {
               test.set(new Random().nextInt(15));
               test.get();
            };
        }.start();
        new Thread() {
            public void run() {
               test.set(new Random().nextInt(25));
               test.get();
            };
        }.start();
        new Thread() {
            public void run() {
               test.set(new Random().nextInt(35));
               test.get();
            };
        }.start();
    }
}

 

 

对于Java concurrent包里的并发,有这么一段话:

什么时候选择用 ReentrantLock 代替 synchronized

既然如此,我们什么时候才应该使用 ReentrantLock 呢?

答案非常简单 —— 在确实需要一些 synchronized 所没有的特性的时候,

比如时间锁等候、可中断锁等候、无块结构锁、多个条件变量或者锁投票。 

ReentrantLock 还具有可伸缩性的好处,应当在高度争用的情况下使用它,

但是请记住,大多数 synchronized 块几乎从来没有出现过争用,

所以可以把高度争用放在一边。我建议用 synchronized 开发,

直到确实证明 synchronized 不合适,而不要仅仅是假设如果使用 ReentrantLock “性能会更好”。

请记住,这些是供高级用户使用的高级工具。

一如既往,首先要把事情做好,然后再考虑是不是有必要做得更快。

 

ref:

http://blog.csdn.net/ghsau/article/details/7461369

http://blog.csdn.net/fw0124/article/details/6672522

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics