Java类允许多个线程读取或同时修改一个

时间:2011-11-22 16:12:42

标签: java multithreading synchronization

假设你有以下课程:

class A {
    private Foo foo = new Foo();
    Foo getFoo() {
        return foo; //foo.clone()?
    }
    void modifyFoo() {
        //modify this.foo
        //...
    }
}

我想允许:

  • 要么多个线程调用getFoo()
  • 或一个线程来调用modifyFoo()
  • 一旦线程想要修改foo,在执行修改之后,没有其他新的getFoo()调用到达,直到修改完成。

Java中是否存在针对此问题的类,或者我是否必须实现它?如果我必须实现它,那么我该如何实现它以确保线程安全?

4 个答案:

答案 0 :(得分:12)

听起来你正在寻找的是一个读写锁,幸运的是,java提供了一个,ReentrantReadWriteLock。您可以按如下方式使用它:

class A {
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private Foo foo = new Foo();
    Foo getFoo() {
        lock.readLock().lock();
        try {
            Foo tmp = foo; //foo.clone()?
        } finally {
            lock.readLock().unlock();
        }
        return tmp;
    }
    void modifyFoo() {
        lock.writeLock().lock();
        try {
            //modify this.foo
            //...
        } finally {
            lock.writeLock().unlock();
        }
    }
}

这将允许任意数量的线程同时调用getFoo(),但只允许一个线程调用modifyFoo()。当调用foo时,线程将阻塞直到释放所有读锁,然后开始执行并阻止获取任何新的读锁,直到它完成为止。仍然需要考虑并发问题,因为返回的Foo可以被调用getFoo的代码修改,但这应该提供您需要的基本工具。

答案 1 :(得分:4)

您应该使用ReentrantReadWriteLock。多个线程可以读取,一个线程可以写入阻塞所有读取的线程。

答案 2 :(得分:1)

class A {
    private volatile Foo foo = new Foo();
    Foo getFoo() {
        return foo; //foo.clone()?
    }
    void synchronized modifyFoo() {
        //modify this.foo
        //...
    }
}

synchronized关键字确保modifyFoo()是原子的,也就是说,不允许多个线程一次调用它。 volatile关键字确保对foo的读取不会返回缓存版本(如果另一个线程修改了它可能已过时),而是返回当前正确的值。

答案 3 :(得分:0)

你应该可以使用同步块。

class A {
    private Foo foo = new Foo();

    Foo getFoo() {
        return foo;
    }

    void modifyFoo() {
        synchronized(foo){
            /* do your modify stuff */
        }
    }
}