允许多个获取同步getter / setter

时间:2013-07-18 13:41:08

标签: java multithreading concurrency synchronized

获取字段访问权限的常用方法是同步getter和setter。使用int的简单示例如下所示:

private int foo = 0;
public synchronized int get(){return this.foo;}
public synchronized void set(int bar){ this.foo = bar;}

现在,虽然这是一种使访问线程安全的安全方法,但它也表明只有一个线程一次只能读取foo

如果很多线程经常阅读foo,并且有时只更新这个变量,那将是一个很大的浪费。相反,getter可以被多个线程同时调用而没有任何问题。

是否有任何关于如何处理此问题的既定模式?或者你会如何以最优雅的方式解决这个问题?

3 个答案:

答案 0 :(得分:5)

看看ReadWriteLock。这个界面是你正在寻找的,它允许多个读者,但只允许一个作家。

一个例子:

private int foo = 0;

private ReadWriteLock rwLock = /* use some implementation of ReadWriteLock here */;

public int get() {
    Lock l = rwLock.readLock();
    int result = 0;
    l.lock();
    try {
        result = this.foo;
    }
    catch(Exception ex) {
        // may throw the Exception here
    }
    finally {
        l.unlock();
    }
    return result;
}

public void set(int bar){ 
    Lock l = rwLock.writeLock();
    l.lock();
    try {
        this.foo = bar;
    }
    catch(Exception ex) {
        // may throw the Exception here
    }
    finally {
        l.unlock();
    }
}

答案 1 :(得分:3)

如果您只是设置并获取变量:那么您可以使用volatile并删除synchronized方法。

如果您对添加的整数进行任何操作,则应使用AtomicInteger

修改

如果存在多次读取字段并更新几次的情况,则会出现名为IMMUTABLE的模式。这是实现线程安全的方法之一。

class ImmutableClass{
        private final int a;

        public ImmutableClass(int a) {
            this.a  = a;
        }

        public int getA(){
            return a;
        }

        /* 
         * No setter methods making it immutable and Thread safe
         */
    }

有关不变性的更详细知识,Java Concurrency In practice是我建议您阅读的最佳资源。

更高级的方法:有Read/Write lock

答案 2 :(得分:0)

对于像你这样简单的例子,设置器中只有一个字段并且没有复杂的逻辑来真正要求互斥,你可以将字段声明为volatile并删除{{1}关键字。

对于更复杂的东西,您可以使用廉价读写锁定模式:

synchronized