我遇到过以下几次代码
class Foo {
private Object lock = new Object();
public void doSomething() {
synchronized(lock) {
...
我感兴趣的是为什么创建一个锁对象而不是写synchronized(this)
?是否可以共享锁定?我依稀记得读到这是一个优化。真的吗?另外,在某些情况下,将锁定声明为final
吗?
答案 0 :(得分:23)
this
上进行同步,因为如果对象本身被用作来自外部的锁,则会破坏内部同步。此外,请记住,synchronized
方法也使用this
作为锁定,这可能会导致不必要的影响。final
以防止在synchronized
块内重新分配锁定对象的情况,从而导致不同的线程看到不同的锁定对象。请参阅另一个问题:Locking on a mutable object - Why is it considered a bad practice? 答案 1 :(得分:3)
想象一下,您有thread1
和thread2
访问method1
,thread3
和thread4
访问method2
的情况。如果this
或thread3
正在访问thread4
,则thread1
上的同步会阻止thread2
和method1
,这不应该thread3
thread4
与method1
无关。对此的优化是使用两个不同的锁而不是锁定整个类实例。
这是我在JavaDoc上发现的一个很好的段落,反映了这一点:
同步语句对于提高并发性也很有用 细粒度的同步。例如,假设MsLunch类有 两个实例字段,c1和c2,从不一起使用。所有 必须同步这些字段的更新,但没有理由 防止c1的更新与c2的更新交错 - 这样做可以通过创建不必要的阻塞来减少并发性
答案 2 :(得分:0)
考虑使用java.util.concurrent包中的锁
例如,这可以提供更优化的锁定 - 使用ReadWriteLock将允许所有读者无需等待即可访问。
答案 3 :(得分:0)
以下是“ReentrantReadWriteLock”的完整工作示例。
public class DataReader {
private static final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private static final Lock read = readWriteLock.readLock();
private static final Lock write = readWriteLock.writeLock();
public static void loadData() {
try {
write.lock();
loadDataFromTheDB());
} finally {
write.unlock();
}
}
public static boolean readData() {
try {
read.lock();
readData();
} finally {
read.unlock();
}
}
public static List loadDataFromTheDB() {
List list = new ArrayList();
return list;
}
public static void readData() throws DataServicesException {
//Write reading logic
}
}