假设你有以下课程:
class A {
private Foo foo = new Foo();
Foo getFoo() {
return foo; //foo.clone()?
}
void modifyFoo() {
//modify this.foo
//...
}
}
我想允许:
getFoo()
modifyFoo()
,getFoo()
调用到达,直到修改完成。Java中是否存在针对此问题的类,或者我是否必须实现它?如果我必须实现它,那么我该如何实现它以确保线程安全?
答案 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 */
}
}
}