同步字段和ReadWriteLocks有什么区别?

时间:2019-04-02 06:28:58

标签: java multithreading synchronization locking thread-synchronization

只想知道以下具有相同功能的代码有何不同

代码1:

    class ReadWriteCounter {
    ReadWriteLock lock = new ReentrantReadWriteLock();

    private Integer count = 0;

    public Integer incrementAndGetCount() {
        lock.writeLock().lock();
        try {
            count = count + 1;
            return count;
        } finally {
            lock.writeLock().unlock();
        }
    }

    public Integer getCount() {
        lock.readLock().lock();
        try {
            return count;
        } finally {
            lock.readLock().unlock();
        }
    }
}

代码2:

class ReadWriteCounter {

private Integer count = 0;

public getCount()
{
   synchronized(count){
   return count;
   }
}

public void setCount(Integer i)
{
     synchronized(count){
         count = i;
       }
   }
}

目的是确保在修改count时,没有其他线程可以访问它进行读取,而在读取时,没有其他线程应该访问它进行写入。哪个是最佳解决方案,为什么?另外,我将在需要编辑字段变量的类中使用它。请提供您的建议。

2 个答案:

答案 0 :(得分:2)

两种解决方案都可以工作,但是实现锁定的方式存在错误。

首先是两种方法的区别: ReentrantReadWriteLock主要用于以下情况中:您的读取次数比写入次数多(通常为10读取:1写入)。这允许读取同时发生而不会互相阻塞,但是在写入开始时,所有读取都会被阻塞。因此,性能是主要原因。

解决您的问题: 您要锁定的对象应该是最终的。在setCount()中,您可以有效地交换对象,这可能会导致当时的读取很脏。

此外,请不要公开要锁定的对象。您锁定的对象应该是私有的且是最终的。原因是,如果您碰巧公开了该对象,则调用者可能会碰巧使用返回的对象本身进行锁定,在这种情况下,您将遇到此类本身之外的组件的争用问题。

答案 1 :(得分:1)

ReentrantReadWriteLock是实现您的想法的最佳方法。 如果两个或多个线程尝试读取计数,则“同步”将仅允许一个线程。 但是每个人都可以在尝试阅读计数时获得计数的价值。