将静态对象用作锁通常是不可取的,因为在整个应用程序中一次只有一个线程可以取得进展。当您有多个类都共享同一个锁时,更糟糕的是,您最终可能会得到一个几乎没有实际并发性的程序。
Java 对每个对象都有内在锁的原因是,对象可以使用同步来保护自己的数据。线程调用对象上的方法,如果需要保护对象免受并发更改,那么您可以将同步关键字添加到对象的方法中,以便每个调用线程必须获取该对象上的锁,然后才能对其执行方法。这样,对不相关对象的调用就不需要相同的锁,并且您有更好的机会让代码实际同时运行。
锁定不一定是您首选的并发技术。实际上,您可以使用多种技术。按偏好降序排列:
1) 尽可能消除可变状态;不可变对象和无状态函数是理想的,因为没有要保护的状态,也不需要锁定。
2)尽可能使用线程限制;如果您可以将状态限制为单个线程,那么您可以避免数据竞争和内存可见性问题,并最大限度地减少锁定量。
3) 优先使用并发库和框架,而不是使用锁定滚动您自己的对象。熟悉 java.util.concurrent 中的类。这些写得比应用程序开发人员可以设法拼凑的任何东西都要好得多。
一旦你尽可能多地完成了上面的 1、2 和 3,那么你可以考虑使用锁定(其中锁定包括 ReentrantLock 和内部锁定等选项)。将锁与被保护的对象相关联可以最小化锁的范围,这样线程就不会持有超过它需要的锁。
此外,如果锁不在被锁定的数据上,那么如果在某个时候您决定使用不同的锁而不是将所有东西都锁定在同一事物上,那么避免死锁可能具有挑战性。锁定需要保护的数据结构使锁定行为更容易推理。
完全避免内在锁的建议可能是过早的优化。首先确保你锁定正确的事情不过是必要的。